看一段代码:
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 class CParent { 6 public: 7 CParent() { cout << "CParent::CParent() "; } 8 ~CParent() { cout << "CParent::~CParent() "; } 9 }; 10 11 class CTest2 : public CParent { 12 public: 13 CTest2() { cout << "CTest2 ::CTest2() "; } 14 ~CTest2() { cout << "CTest2 ::~CTest2() "; } 15 }; 16 17 int main(int argc, char const* argv[]) { 18 CTest2 t1; 19 return 0; 20 }
out:
CTest是子类,CParent是父类
为什么通过派生类创建对象时必须要调用基类的构造函数?
首先,基类的构造函数是不可以被继承的,因为基类和派生类的名字不一样,即使继承了,也不能成为派生类的构造函数;
在设计派生类时,对继承过来的成员变量的初始化工作也的派生类的构造函数完成,但是基类的成员变量大多数是private,
在派生类中无法访问,因此更不能用派生类的构造函数来初始化。所以派生类创建对象时必须调用基类的构造函数。
改写以下:
int main(int argc, char const* argv[]) { CParent* p = new CTest2; //new一个派生类,令基类指针指向派生类 delete p; return 0; }
少了派生类CTest2的析构函数;
delete p; //等价于<==> //p->~CParent(); //free(p);
先调用基类指针的析构,再释放p所指向的内存
如何能调用到派生类的析构函数? -------> 将基类与派生类的析构函数声明为虚函数;
基类和派生类各有一个虚函数,则各有一张虚表,两张虚表的第0项都是各自的析构函数,
5 class CParent { 6 public: 7 CParent() { cout << "CParent::CParent() "; } 8 virtual ~CParent() { cout << "CParent::~CParent() "; } 9 }; 10 11 class CTest2 : public CParent { 12 public: 13 CTest2() { cout << "CTest2 ::CTest2() "; } 14 virtual ~CTest2() { cout << "CTest2 ::~CTest2() "; } 15 };
p->~CParent(); //p指向的派生类,通过派生类访问基类的虚函数, //间接调用,查询子类虚表,子类虚表第0项---子类的析构函数
因此将析构函数声明为虚函数。