(一)有子类继承的基类的析构函数必须是virtual
如果基类的析构函数不是虚函数那也不会报错,但是在工程上是非常危险的,方法实现了多态,析构也要实现多态
否则容易出现这种类似问题
实现一个基类A
class A
{
public:
A();
~A();
int a1;
private:
void* buf;
};
A::A():buf(malloc(16))
{
cout << "Creat A buf " << endl;
}
A::~A()
{
cout << "Drop A buf " << endl;
free(buf);
}
B1和B2继承A类
class B1 : public A
{
public:
B1();
~B1();
private:
void* ch_buf;
};
B1::B1() :ch_buf(malloc(16))
{
cout << "Creat B1" << endl;
}
B1::~B1()
{
free(ch_buf);
cout << "Drop B1 " << endl;
}
class B2 : public A
{
public:
B2();
~B2();
private:
void* ch_buf;
};
B2::B2() : ch_buf(malloc(16))
{
cout << "Creat B2" << endl;
}
B2::~B2()
{
free(ch_buf);
cout << "Drop B2 " << endl;
}
场景模拟,由于构造哪个类由传参决定,所以返回的是基类
A* Creat1(int c)
{
if (c == 1)
return new B1;
if (c == 2)
return new B2;
return nullptr;
}
void Drop1(A* tm)
{
delete tm;
}
int main(int argc, char* argv[])
{
auto test = Creat1(2);
Drop1(test);
return 0;
}
此时就会出现问题,Drop函数里delete只调用了基类的析构函数,但是没有调用子类的析构函数,造成内存泄露
(二)没有子类继承的类应当设置成final,当基类的虚函数被设置成final,则该虚函数不能在子类被重写,类被设置final则无法继承
基类的虚函数被设置成final,则该虚函数不能在子类被重写
(三)虚函数表指针、虚函数表、虚函数之间的关系
(四)override的作用
当子类重写了父类的虚函数,即使不加override也不会报错,但是加上override能提示coder,这个函数是重写自父类中的。
加上override之后,我们在重写的时候,编译器会知道我们是在重写虚函数,如果我们函数的名称写错了,编译器就会报错。
(五)通过虚继承来避免多继承造成的二义性
还是上面的类 A ; B1 : public A ; B2 : public A;
如果此时再来一个类继承自B1 和 B2
class C final:public B1, public B2
{
public:
int c1;
};
class B1 : virtual public A
class B2 : virtual public A