// 多态:默认情况下,编译器只会根据指针类型调用对应的函数,不存在多态
多态是面向对象非常重要的一个特性
同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果
在运行中,可以识别出真正的对象类型,调用对应子类中的函数
多态的要素:
子类重写父类的成员函数(override)
父类指针指向子类对象
利用父类指针调用重写的成员函数
// 虚函数
C++中的多态通过虚函数(virtual function)来实现的.
虚函数:被virtual修饰的成员函数
只要在父类中声明为虚函数,子类中的重写的函数也自动变成虚函数(也就是说子类中可以省略virtual)
class Animal {
public:
virtual void run(){
cout << "Animal::run()" << endl;
}
};
class Cat:public Animal {
public:
void run(){
cout << "Cat::run()" << endl;
}
};
class Dog:public Animal {
public:
void run(){
cout << "Dog::run()" << endl;
}
}
int main() {
Animal *animal1 = new Dog()
animal1->run();
return 0;
}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&7&&&&&&&&&
// 虚函数:虚函数的实现原理是虚表,这个虚表里面存储着最终需要调用的虚函数地址,这个虚表也叫虚函数表
class Animal {
public:
int m_age;
virtual void speak() {
cout << "Animal::speak()" << endl;
}
virtual void run() {
cout << "Animal::run()" << endl;
}
};
class Cat:public Animal {
public:
int m_life;
void speak() {
cout << "Cat::speak()"<<endl;
}
void run() {
cout << "Cat::run()" << endl;
}
}
int main() {
Animal *cat = new Cat()
cat->m_age = 20;
cat->speak();
cat->run();
//汇编:调用Cat::speak
mov eax, dword ptr [cat]
// 取出cat指针变量里面存储的地址值,所以eax里面存放的是Cat对象的地址值
mov edx, dword ptr [eax]
// 取出Cat对象的签名4个字节给edx,所以edx里面存储的是虚表的地址
// 取出虚表中的前面4个字节给eax,所以eax存放的是Cat::speak的函数地址
mov eax, dword ptr [edx]
call eax
return 0;
}
虚表(x86环境的图)
内存地址 内存数据 内存地址 内存数据
cat 0x00E69B60 虚表 0x00B89B64
0x00E69B61 0x00B89B64 0x00B89B65 0x00B814E7
0x00E69B62 0x00B89B66
0x00E69B63 0x00B89B67
&m_age 0x00E69B64 0x00B89B68
0x00E69B65 20 0x00B89B69 0x00B814CE
0x00E69B66 0x00B89B6A
0x00E69B67 0x00B89B6B
&m_life 0x00E69B68
0x00E69B69 0 Cat::speak的调用地址:0x00B814E7
0x00E69B6A
0x00E69B6B Cat::run的调用地址:0x00B814CEE
// 所有的Cat对象(不管在全局区,栈,堆)共用同一份虚表
// 虚析构函数
含有虚函数的类,应该讲虚析构函数声明为虚函数(虚析构函数)
delete父类指针时,才会调用子类的析构函数,保证析构的完整性
// 纯虚函数
没有函数体且初始化为0的虚函数,用来定义接口规范.
含有纯虚函数的类叫做抽象类(abstract Class),不可以实例化,抽象类也可以包含非抽象函数,如果父类是抽象类,子类没有完全实现纯虚函数,那么这个子类依然是抽象类.
class Animal {
public:
virtual void speak() = 0;
virtual void run() = 0;
};
// 多继承 - 虚函数
C++允许一个类可以有多个父类(不建议使用,会增加程序设计复杂度)
如果子类继承的多个父类都有虚函数,那么子类对象就会产生对应的多张虚表
C++,多态
最新推荐文章于 2024-03-29 18:27:47 发布