#include <iostream>
using namespace std;
/*
多态的理解 其中面向对象四大特征之一 其余为封装 抽象 继承
可以简单概括为“一个接口 多种方法”
1.其中C++多态性体现在编译期多态和运行期多态 编译期多态如模板函数,其中函数重载与多态无关。
运行期多态则是具体引用的对象在运行时才可以确定,通常主要通过虚函数来实现,并且一定要有继承关系。
有虚函数,则可以重写这个函数,这里要注意不是重载,也不是覆盖(父类的方法前面无virtual)。
2.理解(parent* pa = new child();)定义一个父类指针,指向子类对象,调用函数在运行期间
动态绑定到指针实际所指的对象。
3.Tuna *pTuna = new Tuna;// 使用new 在自由存储区实例化 通过指针调用delete
不会调用派生类的析构函数 可将基类析构函数声明为虚函数
4.Tuna MyDinner;//局部变量方式在栈中实例化
5.编译器为实现了虚函数的基类和重写的这个函数的派生类分别创建一个虚函数表
(VFT,virtual function table)。base类和derived类都有自己的虚函数表,
实例化这些类的对象时,将创建一个隐藏的指针(VFT*),他指向相应的VFT,可将其视为一个
包含函数指针的静态数组,每个指针指向相应虚函数。
6.抽象基类(ABC abstract base class)为不能被实例化的基类,用来派生出其他类。
讲指针或者引用的类型指定为抽象基类,声明所有派生类都必须实现其函数。
*/
class parent
{
public:
parent() {}
// 父类的虚函数
virtual void eat()
{
std::cout << "Parent eat." << std::endl;
}
// 注意这个并不是虚函数!!!
void drink()
{
std::cout << "Parent drink." << std::endl;
}
};
class child : public parent
{
public:
child() {}
// 子类重写了父类的虚函数
void eat()
{
std::cout << "Child eat." << std::endl;
}
// 子类覆盖了父类的函数,注意由于父类的这个函数
// 并不是虚函数,所以不存在继承后重写的说法
void drink()
{
std::cout << "Parent drink." << std::endl;
}
// 子类特有的函数
void childLove()
{
std::cout << "Child love playing." << std::endl;
}
};
int main()
{
parent* pa = new child();
pa->eat(); // 运行期多态的体现!!!
pa->drink(); // 这里调用的还是父类的drink,所以并不是多态!!!
// pa->childLove(); // 编译出错,父类的指针不能调用父类没有的函数
return 0;
}
多态的理解 其中面向对象四大特征之一 其余为封装 抽象 继承
可以简单概括为“一个接口 多种方法”
1.其中C++多态性体现在编译期多态和运行期多态 编译期多态如模板函数,其中函数重载与多态无关。
运行期多态则是具体引用的对象在运行时才可以确定,通常主要通过虚函数来实现,并且一定要有继承关系。
有虚函数,则可以重写这个函数,这里要注意不是重载,也不是覆盖(父类的方法前面无virtual)。
2.理解(parent* pa = new child();)定义一个父类指针,指向子类对象,调用函数在运行期间
动态绑定到指针实际所指的对象。
3.Tuna *pTuna = new Tuna;// 使用new 在自由存储区实例化 通过指针调用delete
不会调用派生类的析构函数 可将基类析构函数声明为虚函数
4.Tuna MyDinner;//局部变量方式在栈中实例化
5.编译器为实现了虚函数的基类和重写的这个函数的派生类分别创建一个虚函数表
(VFT,virtual function table)。base类和derived类都有自己的虚函数表,
实例化这些类的对象时,将创建一个隐藏的指针(VFT*),他指向相应的VFT,可将其视为一个
包含函数指针的静态数组,每个指针指向相应虚函数。
6.抽象基类(ABC abstract base class)为不能被实例化的基类,用来派生出其他类。
讲指针或者引用的类型指定为抽象基类,声明所有派生类都必须实现其函数。