C++:构造函数,析构函数详解

编辑: admin 分类: c#语言 发布时间: 2021-12-12 来源:互联网
目录
  • 前言
  • 一、面向对象
  • 二、构造函数
    • 1.基本概念
    • 2.构造函数重载
      • 1.构造函数分类
      • 2.有参构造函数:
      • 3.有参构造函数3个调用规则:
      • 4.拷贝构造函数
      • 5.析构函数
  • 总结

    前言

    上期了解C++类中有public、protected、private三种访问权限。

    肯定会有人疑惑,C++为什么要设置这三个权限呢

    本期内容就是围绕上面的问题展开说明

    一、面向对象

    开始的文章就提到过,类是(OOP)面向对象编程的基础

    那么面向对象编程究竟是个什么东东呢

    百度百科是这样解释的

    在这里插入图片描述

    通俗的来说就是利用代码将现实世界的事物抽象出来,使代码更具有真实事物的行为

    简单举个栗子

    狗是人类的朋友,有很多人养狗做宠物

    宠物狗有名字,年龄,毛发颜色,等等特征

    狗还会吃饭,喝水,汪汪汪之类的行为

    如果利用代码抽象一个小狗类

    这些名字,年龄等就对应成员变量

    吃饭喝水等行为就是成员函数

    上代码

    class Dog
    {
    protected:
    	int Age;
    	string Name;
    	string Color;
    public:
    	void Eating()
    	{
    		cout << "吃狗粮" << endl;
    	}
    	void Drinking()
    	{
    		cout << "喝水水" << endl;
    	}
    	void Wangwangwang()
    	{
    		cout << "汪汪汪!!!" << endl;
    	}
    };
    

    在现实世界中狗的名字我们可以改,但年龄和颜色我们是无法改变的,就比如狗的颜色是它本身DNA决定的。我们可以分辨颜色是因为我们视力没有问题,可以通过看的方式访问狗的颜色

    所以我们通常在代码里将成员变量设置成protected属性

    让外部无法直接访问,就像我们无法直接去看狗的DNA序列一样。

    所以通常会定义一些成员函数来间接访问成员变量(这里上期讲解遗漏了,下面补充一下)

    Protected和private无法在类外访问,但可以在自己的类内部被成员函数访问(对外接口)
    而将这些成员函数放在public下,在类外使用这些成员函数,就相当于间接访问无法访问的变量
    这就体现出C++面向对象中封装的特性

    我们看看百度百科中对封装的介绍

    在这里插入图片描述

    简单 的说,外部使用一个封装好的类的时候只会考虑某些接口的特定功能,而并不会关心内部的具体实现细节。

    具体看下图:

    在这里插入图片描述

    那么进入主题,看看封装的具体技术

    二、构造函数

    1.基本概念

    基本概念:构造函数是类的成员函数,作用是在类创建对象时用于初始化对象。

    特点:函数名和类名相同且不用写返回值,在创建对象时会自动调用。

    语法:函数名( 形参列表 ){ 函数实现 }

    注意:

    1.构造函数不需要返回值类型

    2.构造函数的函数名和类名相同

    在这里插入图片描述

    代码如下:

    class MyClass
    {
    protected:
    	int i;
    	char c;
    	string str;
    public:
    	void print()//用于显示成员变量
    	{
    		cout << "i = " << i << endl;
    		cout << "c = " << c << endl;
    		cout << "str = " << str << endl;
    	}
    	MyClass()//构造函数
    	{
    		i = 5;
    		c = 'a';
    		str = "str in MyClass";
    	}
    };
    void test()
    {
    	//创建对象  cla
    	MyClass cla;
    	//调用 成员函数print
    	cla.print();
    }
    int main()
    {
    	test();
    	return 0;
    }
    

    运行效果:

    在这里插入图片描述

    可见我们只是创建了一个对象,并没有对这个对象做任何操作。

    我们不用自己调用构造函数,编译器在创建对象时自动调用构造函数,为变量初始化。

    2.构造函数重载

    1.构造函数分类

    构造函数大概分无参构造、有参构造、拷贝构造三种

    上述代码中的构造函数就是一个典型的无参构造

    2.有参构造函数:

    例如以下代码:(有参构造的3个重载)

    MyClass(int i)
    {
    	this->i = i;
    }
    MyClass(int i, char c)
    {
    	this->i = i;
    	this->c = c;
    }
    MyClass(int i,char c,string str)
    {
    	this->i = i;
    	this->c = c;
    	this->str = str;
    }
    

    3.有参构造函数3个调用规则:

    括号法:

    //使用有参构造函数创建对象   cla2,cla3,cla4
    MyClass cla2(10);
    MyClass cla3(10, 'b');
    MyClass cla4(10, 'b', "str in MyClass_cla2");
    

    等号法:

    //使用有参构造函数创建对象(等号法)
    MyClass cla5 = 10;
    MyClass cla6 = (10, 'b');
    

    直接调用构造函数

    //使用有参构造函数创建对象(调用构造函数)
    MyClass cla7 = MyClass(10);
    MyClass cla8 = MyClass(10, 'b');
    MyClass cla9 = MyClass(10, 'b', "str in MyClass");
    

    4.拷贝构造函数

    MyClass(MyClass& cla)
    {
    	this->i = cla.i;
    	this->c = cla.c;
    	this->str = cla.str;
    }
    

    注意:拷贝构造函数的形参是自身类型的引用

    拷贝构造函数调用

    //使用拷贝构造函数创建对象
    MyClass cla11(cla8);
    MyClass cla12 = cla9;
    

    5.析构函数

    基本概念:在对象被释放时编译器会自动调用析构函数,用于释放对象中变量的内存空间

    语法:函数名( 形参列表 ){ 函数实现 }

    注意:

    1.构造函数不需要返回值类型

    2.构造函数的函数名为 ~(类名)

    特点:函数名和类名相同且不用写返回值,在创建对象时会自动调用。

    有人会问,对象内存被释放时成员变量内存空间不是也被释放了吗

    我们先看一段代码

    class MyClass
    {
    protected:
    	int* p = new int;
    public:
    	MyClass(int i)
    	{
    		*p = i;
    	}
    };
    

    这个MyClass类,类成员变量中在内存堆区开辟一个整型变量

    堆区内存需要手动释放,不然会造成内存泄漏,此时析构函数就派上用处了

    以下为析构函数代码实现:
    ~MyClass()
    {
    	delete p;
    	p = NULL;
    }
    

    由于制作仓促,如有错误敬请指正

    总结

    本期简单介绍OOP面向对象编程和构造函数,析构函数。

    【文章出处:http://www.1234xp.com/tbm.html转载请保留出处】