接上一篇文章
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函數的類都應該有一個虛析構,這句話的意思可能是如果一個類要作爲基類使用,那麼最好把這個類的析構函數改寫成虛析構函數。