zoukankan      html  css  js  c++  java
  • c++ 虚继承与继承的差异 (转)

    转自:CSDN dqjyong

    原文链接:http://blog.csdn.net/dqjyong/article/details/8029527

    前面一篇文章,说明了在C++ 虚继承对基类构造函数调用顺序的影响。经过仔细推敲,发现没有彻底说清楚虚继承与普通继承之间的关系。所以用下面的文字再说明一下。

    首先,重复一下虚拟继承与普通继承的区别有:

    假设derived 继承自base类,那么derived与base是一种“is a”的关系,即derived类是base类,而反之错误;

    假设derived 虚继承自base类,那么derivd与base是一种“has a”的关系,即derived类有一个指向base类的vptr。

    因此虚继承可以认为不是一种继承关系,而可以认为是一种组合的关系。因为虚继承有着“继承”两个关键字,那么大部分人都认为虚继承与普通继承的用法没什么太大的不同。由此用在继承体系中,这种将虚继承认为是普通继承的危害更佳大。下面先用一个例子来说明问题:

     

    class base
    {
    public:
        base(){cout<<"base::base()!"<<endl;}
        void printBase(){cout<<"base::printBase()!"<<endl;}
    };
    
    class derived:public base
    {
    public:
        derived(){cout<<"derived::derived()!"<<endl;}
        void printDerived(){cout<<"derived::printDerived()!"<<endl;}
    };

    上面是普通继承实现,在实际应用中,我们可以使用下面的代码进行类型转换:

     

     
    int main(int argc, const char * argv[])
    {
        derived oo;
        base oo1(static_cast<base>(oo));
        oo1.printBase();
        derived oo2 = static_cast<derived&>(oo1);
        oo2.printDerived();
        return 0;
    }
    编译无错误,而且会得出正确的结果。其结果为:
    base::base()! derived::derived()! base::printBase()! derived::printDerived()!

    而将上面的普通继承变成虚拟继承,如下代码:

     

    class base1
    {
    public:
        base1(){cout<<"base::base()!"<<endl;}
        void printBase(){cout<<"base::printBase()!"<<endl;}
    };
    
    class derived1:virtual public base1
    {
    public:
        derived1(){cout<<"derived::derived()!"<<endl;}
        void printDerived(){cout<<"derived::printDerived()!"<<endl;}
    };
    
    int main(int argc, const char * argv[])
    {
        derived1 oo;
        base1 oo1(static_cast<base1>(oo));
        oo1.printBase();
        derived1 oo2 = static_cast<derived1&>(oo1);
        oo2.printDerived();
        return 0;
    }
    编译上面的代码,提示如下:

    可以看到不能将基类通过static_cast转换为继承类。我们知道c++提供的强制转换函数static_cast对于继承体系中的类对象的转换一般是可行的。那么这里为什么就不可以了呢?还是需要从虚拟继承的内部实现来说明问题。

     

    virtual base class的原始模型是在class object中为每一个有关联的virtual base class加上一个指针vptr,该指针指向virtual基类表。有的编译器是在继承类已存在的virtual table直接扩充导入一个virtual base class table。不管怎么样由于虚继承已完全破坏了继承体系,不能按照平常的继承体系来进行类型转换。

    不管怎么样,虚继承在类型转换是一定要十分注意。不要轻易使用虚继承,更不要在虚继承的基础上进行类型转换,切记切记!

  • 相关阅读:
    Oracle逻辑备份与恢复
    Java调用webservice接口方法
    Weblogic11g下调WebService出现的一系列问题
    数字转中文【适用于金额转换和普通数字转换】
    Tomcat6环境JBPM4.4报错:java.lang.ClassNotFoundException: de.odysseus.el.util.SimpleResolver
    Hibernate之Criteria的完整用法
    Oracle SQL Developer连接报错(ORA-12505)
    Windows Storage Server 2008 R2 Standard(64位)之ASM(Automated Storage Manager)管理
    REHL5.5 linux的postfix的邮件服务器配置 (笔记)
    JVM中class文件探索与解析
  • 原文地址:https://www.cnblogs.com/panweishadow/p/3350712.html
Copyright © 2011-2022 走看看