void *p = new ClassA();
delete p; //错误。不会调用ClassA的析构函数
delete (ClassA*)p; //正确。指明指针类型
ClassA *lpA = new ClassA();
void *q = lpA;
delete q; //错误。不会调用ClassA的析构函数
delete (ClassA*)q; //正确。指明指针类型
class ClassA
{
public:
ClassA(){TRACE("ClassA constructor!/n");};
~ClassA(){TRACE("ClassA destructor!/n");};
};
class ClassB : public ClassA
{
public:
ClassB(){TRACE("ClassB constructor!/n");};
~ClassB(){TRACE("ClassB destructor!/n");};
};
ClassA *p1 = new ClassB(); //先调用ClassA的构造函数。再调用ClassB的构造函数。(先执行基类构造,再执行继承类构造)
delete p1; //只调用ClassA的析构函数。因为p1是ClassA
ClassA *p2 = new ClassB();
delete (ClassB*)p2; //先调用ClassB的析构函数。再调用ClassA的析构函数。(先执行继承类析构,再执行基类析构)
ClassA *p3 = new ClassB();
delete (ClassA*)p3; //同delete p1;
//ClassB *p4 = new ClassA(); //不能由基类转化为继承类
//delete p4;
输出:
ClassA constructor!
ClassB constructor!
ClassA destructor!
ClassA constructor!
ClassB constructor!
ClassB destructor!
ClassA destructor!
ClassA constructor!
ClassB constructor!
ClassA destructor!
结论:
1、继承类创建时先执行基类的构造函数,再执行继承类的构造函数。
析构的时候顺序相反,先执行继承类的析构函数,再执行基类的析构函数。
2、执行 delete a; 时,是根据 a 的类型来决定如何释放对象。与它指向的对象类型无关
class ClassA
{
public:
ClassA(){TRACE("ClassA constructor!/n");};
virtual ~ClassA(){TRACE("ClassA destructor!/n");};
};
class ClassB : public ClassA
{
public:
ClassB(){TRACE("ClassB constructor!/n");};
~ClassB(){TRACE("ClassB destructor!/n");};
};
ClassA *p1 = new ClassB();
delete p1; //先调用ClassB的析构函数,再调用ClassA的析构函数。因为virtual ~ClassA()