根据《effective C++》第7章所述,new的一个子类对象赋值给基类指针delete的时候为了防止子类的析构函数没有调用要在基类的析构函数加上virtual 关键字:
#include <stdint.h>
#include <iostream>
#include <iomanip>
#include <vector>
class A
{
public:
A() : a(0)
{
}
virtual ~A()
{
std::cout << "delete A" << std::endl;
}
private:
int a;
};
class B : public A
{
public:
B() : A(), b(1), c(2) {}
~B()
{
std::cout << "delete B" << std::endl;
}
private:
int b;
int c;
// members
};
int main()
{
A *a1 = new B;
delete a1;
}
成功析构!
然而根据《more effective C++》第三章所说,用一个数组存放基类的指针指向子类的对象,使用delete []来释放子类的对象会出现内存泄漏(crash):
#include <stdint.h>
#include <iostream>
#include <iomanip>
#include <vector>
class A
{
public:
A() : a(0)
{
}
virtual ~A()
{
std::cout << "delete A" << std::endl;
}
private:
int a;
};
class B : public A
{
public:
B() : A(), b(1), c(2) {}
~B()
{
std::cout << "delete B" << std::endl;
}
private:
int b;
int c;
// members
};
int main()
{
A *a1 = new B[2];
delete[] a1;
}
结果是什么也没有输出。
一个朴素的解决办法是不要使用new一个指针数组,改用vector或array来存放指针:
#include <stdint.h>
#include <iostream>
#include <iomanip>
#include <vector>
class A
{
public:
A() : a(0)
{
}
virtual ~A()
{
std::cout << "delete A" << std::endl;
}
private:
int a;
};
class B : public A
{
public:
B() : A(), b(1), c(2) {}
~B()
{
std::cout << "delete B" << std::endl;
}
private:
int b;
int c;
// members
};
int main()
{
std::vector<A *> v;
v.push_back(new B);
v.push_back(new B);
for (int i = 0; i < v.size(); ++i)
delete v[i];
}
这样即使用一个基类指针指向子类指针也能正确地析构