多态:
静态多态---->通过函数重载实现
动态多态------>通过虚函数实现
虚函数不是说在基类中定义一个,然后再在派生类中再定义一个和基类除了函数体不同,其他都相同的函数就是虚函数。
虚函数是将基类中需要在派生类重新构造的同名函数加上virtual关键字。
1,多重继承--->只需对直接基类的构造函数初始化。
2,虚基类------->对于虚基类的继承方式,所有基类都由派生类用初始化列表初始化。
可以通过基类指针或者引用来访问基类和派生类的这些同名函数。
- #pragma once
- #include <iostream>
- using namespace std;
-
- class animal
- {
- public:
- int foot;
- animal(int f) :foot(f) {}
- void print()
- {
- cout << "animal_foot:"<<foot << endl;
- }
- };
- class bird :public animal
- {
- public:
- int weight;
- bird(int f, int w) :animal(f), weight(w) {}
- void print()
- {
- cout << "bird_foot:" <<foot<<"bird_wieght:"<<weight << endl;
- }
- };
- class sparrow :public bird
- {
- public:
- int fly_height;
- sparrow(int f, int w, int h) :bird(f,w), fly_height(h) {}
- void print()
- {
- cout << "sparrow_foot:" << foot << "sparrow_weight:" << weight << "sparrow_fly_heigth:" << fly_height << endl;
- }
- };
-
- #include "base.h"
-
- int main()
- {
- animal an(4);
- bird bd(2,20);
- sparrow sp(2, 20, 300);
- animal* p = &an;
- p->print();
- p = &bd;
- p->print();
- p = &sp;
- p->print();
-
- return 0;
- }
输出:

结论:如果不是虚函数,则派生类给基类指针或者引用赋值,就只是赋值派生类含有的基类部分。
只需要在第一个类的同名函数之前加上一个virtual之后:
- #pragma once
- #include <iostream>
- using namespace std;
-
- class animal
- {
- public:
- int foot;
- animal(int f) :foot(f) {}
- virtual void print()
- {
- cout << "animal_foot:"<<foot << endl;
- }
- };
- class bird :public animal
- {
- public:
- int weight;
- bird(int f, int w) :animal(f), weight(w) {}
- void print()
- {
- cout << "bird_foot:" <<foot<<" bird_wieght:"<<weight << endl;
- }
- };
- class sparrow :public bird
- {
- public:
- int fly_height;
- sparrow(int f, int w, int h) :bird(f,w), fly_height(h) {}
- void print()
- {
- cout << "sparrow_foot:" << foot << " sparrow_weight:" << weight << " sparrow_fly_heigth:" << fly_height << endl;
- }
- };
-
- #include "base.h"
-
- int main()
- {
- animal an(4);
- bird bd(2,20);
- sparrow sp(2, 20, 300);
- animal* p = &an;
- p->print();
- p = &bd;
- p->print();
- p = &sp;
- p->print();
-
- return 0;
- }
输出:

结论:
可以通过基类指针或者引用来访问基类和派生类的这些同名函数。
基类指针和引用不仅可以访问基类同名函数,也可以访问派生类的同名函数。

注意:一个类(不是类对象)含有一个虚函数表,而一个类对象含有一个虚表指针。
建立对象,执行构造函数时,将这个虚函数表(数组)的地址赋给对象的虚表指针,通过虚表指针就可以访问到指定类的虚函数。
几个虚函数原理文章