1.虚析构函数
#include <iostream>
using namespace std;
// 基类
class A
{
public:
A()
{
cout << "A 的构造函数" << endl;
}
virtual ~A()
{
cout << "A 的析构函数" << endl;
}
};
// 构造的顺序:沿着类的继承路径网上最顶层的父类,从最顶层的父类依次往下开始构造
// 析构的顺序:从当前类开始沿着类的继承路径网上查找父类,依次析构,直到最顶层父类为止
class B:public A
{
public:
B()
{
cout << "B 的构造函数" << endl;
}
~B()
{
cout << "B 的析构函数" << endl;
}
};
// 通过基类指针释放派生类对象
void func(A *pa)
{
// pa 是 A 的指针,delete 释放的时候调用的 A 的析构函数
// 如果将 基类的 析构函数设置为虚函数,则在调用 delete释放的时候,调用的是传过来对象的析构函数
delete pa;
}
int main()
{
B *pb = new B;
func(pb);
return 0;
}
2.多态的原理
#include <iostream>
using namespace std;
class Animal
{
public:
virtual void eat()
{
cout << "动物吃饭" << endl;
}
virtual void func1()
{
cout << "动物吃饭" << endl;
}
virtual void func2()
{
cout << "动物吃饭" << endl;
}
virtual void func3()
{
cout << "动物吃饭" << endl;
}
virtual void func4()
{
cout << "动物吃饭" << endl;
}
void sleep()
{
cout << "动物睡觉" << endl;
}
private:
int a;
};
class Cat : public Animal
{
public:
virtual void eat()
{
cout << "猫吃鱼" << endl;
}
void sleep()
{
cout << "猫睡觉" << endl;
}
private:
int b;
};
void func(Animal *pa)
{
// 如何确定传过来的对象类型?
// ====> 如何找到 传过来的对象的相应函数?
// 通过虚函数 ========> 虚函数干了什么?
// 1、通过基类指针 找到 虚函数指针
// 2、通过虚函数指针找到 虚函数表
// 3、在虚函数表中找到 需要执行的函数
pa->eat(); // pa->vfptr->eat()
pa->sleep();
}
int main()
{
cout << sizeof(Animal) << endl;
cout << sizeof(Cat) << endl;
Animal a;
Cat c,c1,c2,c3;
func(&a);
func(&c);
return 0;
}
3.构造函数中能否实现多态
// ====> 构造函数中是无法实现多态的,原因:
// 虚函数指针在初始化的时候,是分步进行初始化的,执行到哪一个类的构造函数,该指针就指向这个类的虚函数表
// 对于 Cat
// 1、先调用Animal的构造函数,则 vfptr 指向Animal的虚函数表
// 2、调用 Cat 的构造函数, 则 vfptr 指向Cat的虚函数表
// 虚函数指针在初始化的时候,是分步进行初始化的,执行到哪一个类的构造函数,该指针就指向这个类的虚函数表
// 对于 Cat
// 1、先调用Animal的构造函数,则 vfptr 指向Animal的虚函数表
// 2、调用 Cat 的构造函数, 则 vfptr 指向Cat的虚函数表