C++中多态

多态成立的三个条件

  1. 有继承
  2. 有函数重写
  3. 有父类指针(父类引用)指向子类对象
#include 
#include 
using namespace std;
//多态成立的三个条件
//要有继承,虚函数重写,父类指针指向子类对象
 
class Parent
{
          private:
        int a   ;
          public: 
          Parent(int a =0)
          {
              this->a = a; 
          }
          virtual void print() //1,动手脚 特殊处理   虚函数表 
          {
              cout<<"我是巴巴"<b = b; 
          }
          virtual void print()
          {
              cout<<"我是儿子"<print();//2,动手脚会有多态发生  特殊处理
    //传来子类对象,执行子类的print函数,传来父类对象执行父类的print函数 
    //c++编译器根本不需要区分是子类对象还是父类对象
    //父类对象和子类对象分别有vptr指针  ===>虚函数表===>函数的入口地址
    //迟邦定(运行时,c++编译器才去判断) 
}

int main()
{
    Parent p1; //3,动手脚 用类定义对象的时候  c++编译器会在对象 中添加一个vptr指针 
    Child c1;
    HowToPlay(&p1);
    HowToPlay(&c1);
    system("pause");
    return 0;
}

多态原理

  1. 当类中声明虚函数时,编译器会在类中生成一个虚函数表
  2. 虚函数表是一个存储类成员函数指针的数据结构
  3. 虚函数表是由编译器自动生成与维护的
  4. virtual成员函数会被编译器放入虚函数表中
  5. 存在虚函数时,每个对象中都有一个指向虚函数表的指针(vptr指针)


    image.png

    image.png

    image.png

    说明1:通过虚函数表指针VPTR调用重写函数是在程序运行时进行的,因此需要通过寻址操作才能确定真正应该调用的函数。而普通成员函数是在编译时就确定了调用的函数。在效率上,虚函数的效率要低很多。
    说明2: 出于效率考虑,没有必要将所有成员函数都声明为虚函数

  • 证明vptr的存在
#include 
using namespace std;
//多态成立的三个条件
//要有继承,虚函数重写,父类指针指向子类对象
class Parent1
{
            private:
        int a   ;
            public: 
              Parent1(int a =0)
              {
                this->a = a; 
              }
              void print() //1,动手脚 特殊处理   虚函数表 
              {
                cout<<"我是巴巴"<a = a; 
          }
          virtual void print() //
          {
            cout<<"我是巴巴"<
  • vptr指针初始化
    对象在创建时,由编译器对VPTR指针进行初始化
    只有当对象的构造完全结束后VPTR的指向才最终确定
    父类对象的VPTR指向父类虚函数表
    子类对象的VPTR指向子类虚函数表


    image.png

你可能感兴趣的:(C++中多态)