#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
class Animal
{
public: //不声明public:的情况下,默认是在私有权限下
virtual void speak()
{
//当父类写了虚函数后, 类内部结构发生了改变,多了一个vfptr
//vfptr 虚函数指针 -> 指向vftable虚函数表
//虚函数表记录着 虚函数的入口地址
//当父类指针或引用指向子类对象时,发生多态,调用时从虚函数中找函数入口地址
cout << "动物在说话" << endl;
}
};
class Cat : public Animal
{
public:
void speak()
{
cout << "小猫在说话" << endl;
}
};
class Dog : public Animal
{
public:
virtual void speak()
{
cout << "小狗在说话" << endl;
}
};
void doSpeak(Animal& animal)
{
animal.speak();
}
void test01()
{
Cat cat;
//父类的引用接收子类的对象,指针和引用 是可以直接转换的
doSpeak(cat); //Animal& animal = cat
//静态联编:如果函数地址在运行钱早就绑定好了,地址早绑定,属于静态联编
//输出动物在说话
//动态联编:想要将函数的地址在运行阶段再绑定,地址晚绑定,属于动态联编
}
void test02()
{
//动态联编:
//在父类的需要晚绑定的的函数前加关键字:virtural
//子类函数前可加可不加
Dog dog;
doSpeak(dog);
//动态联编产生的条件:
//1. 需要有继承对象
//2. 父类中需要有虚函数,子类重写父类的函数
//3. 父类的指针或引用,指向子类的对象
}
void test03()
{
//产生-虚函数表指针 指向 虚函数表
cout << "size of Animal = " << sizeof(Animal) << endl;
//子类继承,不重写
//Cat类的内部虚函数指针指向父类的函数
//重写:&Cat::speak覆盖父类的&Animal::animal
//Animal* aniaml = new Cat
//animal->speak //从Cat类中寻找speak函数
}
int main()
{
test01();
test02();
test03();
return 0;
}
运行结果: