zoukankan      html  css  js  c++  java
  • 虚函数&虚继承

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

    虚函数

    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. 原理

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

  • 相关阅读:
    v-if和v-show的区别
    关于C语言静态链接的个人理解,欢迎指正
    关于C语言中的强符号、弱符号、强引用和弱引用的一些陋见,欢迎指正
    Android: ScrollView监听滑动到顶端和底端
    Android小记之--ClickableSpan
    Android小记之--android:listSelector
    表达式参数
    Http和Socket连接
    Hibernate: merge方法
    Android小代码——设置全屏
  • 原文地址:https://www.cnblogs.com/zoey-liao/p/13983039.html
Copyright © 2011-2022 走看看