接上一篇文章
https://mp.csdn.net/console/editor/html/106482664
条款05:了解C++默默编写并调用了哪些函数
class A
{
};
我们在程序中创建这么一个类,看似是空的类,其实这里面存在C++默认写好并且隐藏的成员函数。
class A
{
public:
A(){} //无参数构造函数
A(const A&){} //拷贝构造函数
~A(){} //析构函数
A& operator=(const A&){} //重载=运算符
}
这么写一般不会出问题。但是在以下几种情况会出问题:
(1)成员变量中含有引用参数。
如下:
class MyClass
{
public:
MyClass(int tmp_value);
int &m_Value;
};
MyClass::MyClass(int tmp_value)
:m_Value(tmp_value)
{
}
void main()
{
MyClass temp_MyClass(10);
MyClass temp_MyClassB(20);
temp_MyClass = temp_MyClassB; //这个操作编译器不允许。写上报错。
}
条款06:若不想使用编译器自动生成的函数,就该明确拒绝。
OK拒绝最常用方法有两个:
(1)将默认函数写出来,写在private里,禁止别人访问。
(2)写个基类,该类就把C++默认写好的这三个函数写成private的。其他要实现的类去private继承他。(不过这样整容易整乱)
条款07:为多态基类生命virtual析构函数
直接看代码
//父类头文件
class MyClass
{
public:
MyClass();
~MyClass();
};
//源文件
#include "myclass.h"
#include<QDebug>
MyClass::MyClass()
{
}
MyClass::~MyClass()
{
qDebug("delete MyClass");
}
//子类
#include"myclass.h"
class MySon : public MyClass
{
public:
MySon();
~MySon();
};
//源文件
#include "myson.h"
#include<QDebug>
MySon::MySon()
{
}
MySon::~MySon()
{
qDebug("delete my son");
}
我们用父对象的指针创建子对象。(工厂模式常用),然后delete掉
MyClass *temp_MyClass = new MySon;
delete temp_MyClass;
后台打印语句为
可以看到,我们析构的时候并没有走子类的析构函数。如果在子类构造函数中申请空间,在子类的析构函数中释放,这样做就会产生内存泄漏。
解决方法是
父类的析构函数前面加上virtual
virtual ~MyClass();
后台打印语句为
注意:如果一个类不会去作为基类这种使用,那么不要用virtual来修饰析构函数。
PS书中说的任何一个带有virtaul函数的类都应该有一个虚析构,这句话的意思可能是如果一个类要作为基类使用,那么最好把这个类的析构函数改写成虚析构函数。