1、不要用基类指针操作派生类对象数组 = = => 基类和派生类的步长不一致
2、虚析构函数:= = => 通过基类指针释放派生类对象
#include <iostream>
// 封装:信息隐藏,对外提供访问控制
// 继承:代码复用
// 多态:功能扩展
using namespace std;
class Animal
{
public:
virtual void sleep()
{
cout << "动物睡觉" <<endl;
}
void eat()
{
cout << "动物吃饭" <<endl;
}
protected:
int a;
int b;
};
class Dog : public Animal
{
public:
void sleep() // 函数重写
{
cout << "狗 趴着睡觉" <<endl;
}
void eat() // 函数重定义
{
cout << "狗 啃骨头" <<endl;
}
protected:
int c;
int d;
};
class Fish : public Animal
{
public:
void sleep() // 函数重定义
{
cout << "鱼 睁着眼睡觉" <<endl;
}
void eat() // 函数重定义
{
cout << "鱼 吃虾米" <<endl;
}
protected:
int c;
int d;
};
// 根据对象的不同,调用不同的函数
// 多态:一种调用形式有多种不同的表现形态
// 实现:继承 + 虚函数 + 类型兼容性原则
// 重写:虚函数的重定义叫 函数重写
// 虚函数:如果基类有一个函数是虚函数,派生类继承的时候,虚函数重写的时候不管前面有没有加 virtual 默认都是虚函数
void func(Animal *pa)
{
// 看实际调用的函数
// 1、看指针 ---> pa 是 Animal * 类型指针
// 2、看函数类型 --> eat 是一个普通函数
// 3、调用 Animal::eat ----> 知道具体该调用的函数 ---> 静态联编 早期联编
pa->eat();
// 1、看指针 ---> pa 是 Animal * 类型指针
// 2、看函数类型 --> sleep 是一个 虚函数
// 3、根据 pa 指向的对象的具体类型,调用该对象的 sleep 函数 ---> 在程序运行阶段才能具体确定执行语句 ---> 动态联编 晚期绑定
pa->sleep();
}
int main()
{
Animal a;
Dog d;
Fish f;
func(&a);
cout << "------------------------------------" << endl;
func(&d);
cout << "------------------------------------" << endl;
func(&f);
return 0;
}
多态实现
#include <iostream>
using namespace std;
class Animal
{
public:
Animal()
{
cout << "Animal 的构造函数" << endl;
this->sleep();
}
virtual void sleep()
{
cout << "动物睡觉" <<endl;
}
void eat()
{
cout << "动物吃饭" <<endl;
}
protected:
int a;
int b;
};
class Dog : public Animal
{
public:
Dog()
{
cout << "Dog 的构造函数" << endl;
sleep();
}
void sleep()
{
cout << "狗 趴着睡觉" <<endl;
}
void eat()
{
cout << "狗 啃骨头" <<endl;
}
protected:
int c;
int d;
};
class Fish : public Animal
{
public:
void sleep()
{
cout << "鱼 睁着眼睡觉" <<endl;
}
void eat()
{
cout << "鱼 吃虾米" <<endl;
}
};
// 多态实现 ---> 虚函数 ---> 虚函数指针
void func(Animal *pa)
{
pa->eat();
// pa->vfptr->sleep();
pa->sleep();
}
int main()
{
Dog d;
return 0;
}
int main1()
{
cout << sizeof(Animal) << endl;
Animal a;
Dog d;
Fish f;
func(&a);
cout << "------------------------------------" << endl;
func(&d);
cout << "------------------------------------" << endl;
func(&f);
return 0;
}