类说虚拟继承

class A           //定义一个类A

{

    public:

        A(){cout << "A called"<< endl;}

        void print(){cout << "A print" <<endl;}

    private:

 

};

 

class B          //定义一个类 B

{

    public:

        B(){cout << "B called" << endl;}

        void print(){cout << "B print" << endl;}

    private:

 

};

class C :public A , public B   //定义一个类C 分别继承自 A ,B

{

       public:

        C(){}

    private:

};

int main(void)

{

       C c;

       c.print();    // 看看类A和类B的定义, 在这里编译器不知道要调用那个父类的print()方法。

                         // 应该这样调用:c.A::print()或者 c.B::print() ;

       getchar();

return 0;

}

 

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class A

{

    public:

        A(){cout << "A called"<< endl;}

        void print(){cout << "A print" <<endl;}

    private:

 

};

 

class B :  public A

{

    public:

        B(){cout << "B called" << endl;}

 

    private:

 

};

class C :  public A

{

    public:

        C(){cout << "C called" << endl;}

           private:

 

};

class D:public B,public C

{

    public:

        D(){cout << "D called" << endl;}

    private:

 

};

int main(void)

{

    D d;

    d.print();             // 在这里编译器也不知道调用那个A的print方法(B的父类还是C的父类). 

                                         // 应该这样调用:c.B::print()或者 c.C::print() ;

    getchar();

    return 0;

}

 

// 解决以上两种情况的另一种方法

//////////////////////////////////////////////////////////////////////////////////////////

class B :  virtual public A

{

    public:

        B(){cout << "B called" << endl;}

 

    private:

 

};

class C :  virtual public A

{

    public:

        C(){cout << "C called" << endl;}

           private:

 

};

这样就相当于说,在没有A类的拷贝时就构造一个,如果已经有了,就用已经有的那一个,这样一来,拷贝只有一份了,二义性消除了

//////////////////////////////////////////////////////////////////////////////////////////

使用虚拟继承:虚拟继承又称作共享继承,这种共享其实也是编译期间实现的,当使用虚拟继承时,上面的程序将变成下面的形式:

#include <iostream.h>

#include <memory.h>

class CA

{

    int k;

public:

    void f() {cout << "CA::f" << endl;}

};

 

class CB : virtual public CA    // 也有一种写法是class CB : public virtual CA

{                                                           // 实际上这两种方法都可以

};

 

class CC : virtual public CA

{

};

 

class CD : public CB, public CC

{

};

 

void main()

{

    CD d;

    d.f();

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

### C++ 中虚拟继承与虚函数表的关系及实现机制 #### 虚拟继承概述 在 C++ 中,当多个派生从同一个基继承时,如果这些派生又被另一个共同的派生继承,则可能会导致重复继承同一基的情况。为了避免这种冗余并节省内存开销,可以使用 `virtual` 关键字来指定虚拟继承。 #### 虚函数表结构变化 对于采用虚拟继承的方式构建出来的层次体系而言,在编译期间会为每一个含有虚函数的对象分配一张或多张 vtable(即虚函数表)。每张表格里记录着相应型的各个成员方法地址;而每个实例内部则保存有指向所属别专属版本列表头部位置的一个指针——vptr (Virtual Table Pointer)[^1]。 #### 多重继承下的特殊处理 特别地,在涉及多重继承的情况下,由于可能存在两个及以上不同路径通往相同的间接祖先节点的情形发生,因此为了确保最终合成的新实体仅保留单一副本而非多次复制同样的成分进去,就需要引入额外的数据结构支持: - **Vbase ptr**: 存储虚基对象空间中最开始的位置。 - **调整偏移量**:用于解决因布局改变而导致访问越界的问题。通过计算相对位移值使得即使是在复杂嵌套关系之中也能准确定位到目标属性所在之处[^4]。 #### 示例代码明 下面给出一段简单的程序片段用来展示上述概念的实际应用效果: ```cpp #include <iostream> using namespace std; class Base { protected: int baseData; public: virtual void showBase() const = 0; // 定义纯虚函数 }; // 使用 virtual 进行单次共享继承 class DerivedA : virtual public Base { private: int derivedAdata; public: void showBase() const override {cout << "DerivedA's view of Base\n";} }; class DerivedB : virtual public Base { private: int derivedBdata; public: void showBase() const override {cout << "DerivedB's view of Base\n";} }; // 同时继承自 DerivedA 和 DerivedB 的新class MultiInherited : public DerivedA, public DerivedB { public: using DerivedA::showBase; // 显示声明要使用的具体版本 }; ``` 在这个例子中,`MultiInherited` 同时继承了 `DerivedA` 和 `DerivedB` ,但由于两者都采用了虚拟方式连接至公共父级 `Base` 上面,所以整个家族树里面就只会存在唯一一份后者之拷贝而已[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值