C++:构造函数,析构函数详解
前言
上期了解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面向对象编程和构造函数,析构函数。