• 虚函数&虚继承


    之前不了解虚继承,一度以为是和虚函数相关的东西,后来查了一下才知道是完全不相关的特性。特此记录一下。

    虚函数

    1. 写法

    中的成员函数,定义时在最左侧加上virtual关键字,就被定义为了虚函数。

    2. 意义

    实现多态性。用父类指针指向子类对象时可以调用子类中的函数(前提:在父类中被定义为虚函数并在子类中进行了覆盖)。

    3. 作用

    基类中的虚函数可以在子类中被重新定义。使用基类指针指向子类对象并调用虚函数时,调用到的会是子类中的函数。
    子类中重新实现的虚函数,其参数列表需要与基类中的虚函数相同。virtual修饰符加不加都可以。
    子类的子类仍然可以重新定义该虚函数。

     #include <iostream>
     using namespace std;
     class A{
      public:
      virtual void func(){
       cout << "I am A." << endl;
      }
     };
     class B: public A{
      public:
      void func(){
       cout << "I am B." << endl;
      }
     };
     class C: public B{
      public:
      void func(){
       cout << "I am C." << endl;
      }
     };
     int main(int argc, const char * argv[]) {
      A* pointer = new C();
      pointer->func(); // 调用结果为: I am C.
      return 0;
     }
    

    4. 原理

    一旦类中有函数被定义为了虚函数,类就会拥有一个虚函数表
    虚函数表中,保存着一系列函数指针,指向这个类中的虚函数实际的起始地址。
    为了能获取到类的虚函数表,类的每个对象中就需要保存一个指针,指向自己的类的虚函数表(vtbl,也称虚表)。这个指针称为虚函数表指针(vptr)。
    当使用基类指针指向子类对象并调用虚函数时,程序会通过对象的虚表指针去子类虚表中查找虚函数的实际地址。
    也是因为这个原因,定义了虚函数的类的对象中会多一个4/8字节(取决于32位/64位)的指针,存于变量的起始位置。

    虚继承

    1. 写法

    一个类型在继承另一个类时加上virtual修饰符,这个继承就是一个虚继承,其基类称为虚基类。

    2. 意义

    虚继承是为了解决C++中的多重继承问题而存在的特性。

    3. 作用

    如果一个子类继承了两个不同的基类,这两个类的继承链中又有相同的基类,那么在子类中,公共基类会被继承两次。
    比如菱形继承:D继承了B、C,B和C又都是A的子类。
    这样会导致两个后果:
    一是浪费空间,公共基类的成员存在两份;
    二是公共基类的成员来自两条不同的继承路径,在使用时不能确定使用的是哪一个,因此存在二义性。
    虚继承可以解决这一问题。
    由虚继承方式被继承的基类在子类的子类中只会存在一份内存结构。

    4. 原理

    虚继承中,子类并不像普通继承那样拥有一份基类的内存结构,而是加了一个虚基类表指针指向虚基类。
    当虚基类的子类被继承时,虚基类表指针也会被继承。
    因此,当某个子类通过不同路径继承了同一个虚基类时,该子类的内存中只会存在一份虚基类的拷贝,避免了冲突。

  • 相关阅读:
    python实现满二叉树递归循环
    二叉树遍历规则,先顺遍历/中序遍历/后序遍历
    满二叉树的循环递归
    python 中的super()继承,搜索广度为先
    UITableview 中获取非选中的cell
    iOS——UIButton响应传参数
    iOS- iPad UIPopoverController
    IPAD之分割视图 SplitViewController
    IOS7 隐藏状态栏
    iOS 强制横屏
  • 原文地址:https://www.cnblogs.com/zoey-liao/p/13983039.html
Copyright © 2020-2023  润新知