Chinaunix首页 | 论坛 | 博客
  • 博客访问: 133214
  • 博文数量: 69
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 602
  • 用 户 组: 普通用户
  • 注册时间: 2014-12-25 20:56
文章分类

全部博文(69)

文章存档

2015年(68)

2014年(1)

我的朋友

分类: LINUX

2015-03-02 21:50:05

2.引入虚继承和直接继承会有什么区别呢

由于有了间接性和共享性两个特征,所以决定了虚继承体系下的对象在访问时必然会在时间和空间上与一般情况有较大不同。

2.1时间:在通过继承类对象访问虚基类对象中的成员(包括数据成员和函数成员)时,都必须通过某种间接引用来完成,这样会增加引用寻址时间(就和虚函数一样),其实就是调整this指针以指向虚基类对象,只不过这个调整是运行时间接完成的。

2.2空间:由于共享所以不必要在对象内存中保存多份虚基类子对象的拷贝,这样较之多继承节省空间。虚拟继承与普通继承不同的是,虚拟继承可以防止出现diamond继承时,一个派生类中同时出现了两个基类的子对象。也就是说,为了保证这一点,在虚拟继承情况下,基类子对象的布局是不同于普通继承的。因此,它需要多出一个指向基类子对象的指针。

4.c++重载、覆盖、隐藏的区别和执行方式

既然说到了继承的问题,那么不妨讨论一下经常提到的重载,覆盖和隐藏
4.1成员函数被重载的特征
(1)相同的范围(在同一个类中); 
(2)函数名字相同; 
(3)参数不同; 
(4)virtual 关键字可有可无。 
4.2“覆盖”是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类); 
(2)函数名字相同; 
(3)参数相同; 
(4)基类函数必须有virtual 关键字。 
4.3“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,特征是:

(1)如果派生类的函数与基类的函数同名,但是参数不同,此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。 
(2)如果派生类的函数与基类的函数同名,但是参数相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。

小结:说白了就是如果派生类和基类的函数名和参数都相同,属于覆盖,这是可以理解的吧,完全一样当然要覆盖了;如果只是函数名相同,参数并不相同,则属于隐藏。


4.4 三种情况怎么执行:

4.4.1 重载:看参数。

4.4.2 隐藏:用什么就调用什么。

4.4.3 覆盖:调用派生类。




c++ 虚继承详解  

2011-04-11 19:42:16|  分类: c/c++学习ING|举报|字号 订阅

#include
using namespace std;
class A
{
 virtual void f(){};
};
class B : public virtual  A{
  
 virtual void f(){};
};
class C: public virtual  A{
 virtual void f(){};
 virtual void t(){};
};
int main() 

   cout<   cout<
此题在vc6.0下结果是 8 12。

回顾一下虚继承的概念:虚继承主要解决在多重继承中的菱形继承问题,也就是说 B和C类同时继承了A类,然后D类继承了B,C类,那么D类的虚表就会有重复的函数指针,虚继承就不会了……。实现方法是,在子类中保存一个父类(虚继承类)的实体,同时保存一个指针指向这个实体。指针+实体都是属于子类,所以sizeof会将两者也算在内。

cout<

 cout<



最后我们来看一个完整的例子以及内存结构布局。图后有相关代码。

 

 VS2003虚继承内存结构图

 有了之前的那个思想,我来讲解下 各个结构体的 sizeof();

代码如下:

struct A

{

    A(int v=100):X(v){};

    virtual void foo(void){}

    int X;

};

 A:很简单 一个虚表指针 +一个 X 一共是8byte

struct B :virtual public A

{

    B(int v=10):Y(v),A(100){};

    virtual void fooB(void){}

    int Y;

};

 B:虚继承,OK 那就是 sizeof(A)+一个指向虚基类的指针4byte+判断B中的虚函数是不是从A继承的,如果是则这一部分是0,如果不是则还要再加4byte 存放 虚表 那么 B一共就是20byte。

struct C : virtual public A

{

    C(int v=20):Z(v),A(100){}

    virtual void fooC(void){}

    int Z;

};

 C的分析同A

 

struct D : public B, public C

{

    D(int v =40):B(10),C(20),A(100),L(v){}

    virtual void fooD(void){}

    int L;

};

 D:公共继承B,C,那么 直接 sizeof(b)+sizeof(C)+自己的一个虚指针-因为B,C都是虚继承A,那么B和C中关于A的指针只要保存一个,所以要减去4个字节,那么D最后一共就是40byte OK

 

int _tmain(int argc, _TCHAR* argv[])

{

   

    A a;

    int *ptr;

    ptr = (int*)&a;

    cout << ptr << " sizeof = " << sizeof(a) <

    for(int i=0;i

    {

        if(ptr[i] < 10000)

        {

             cout << dec << ptr[i]<

        }

        else cout << hex << ptr[i] <<" = " << hex << * ((int*)(ptr[i])) <

    }

 

    cout << "--------------------------------------" <

 

    B b;

    ptr = (int*)&b;

    cout <<"addr:" << ptr << " sizeof = " << sizeof(b) <

    for(int i=0;i

    {

        if(ptr[i] < 10000)

        {

             cout << dec << ptr[i]<

        }

        else cout << hex << ptr[i] <<" = " << hex << * ((int*)(ptr[i])) <

    }

 

    cout << "--------------------------------------" <

   

    D d;

    ptr = (int*)&d;

    cout <<"addr:" << ptr << " sizeof = " << sizeof(d) <

    for(int i=0;i

    {

        if(ptr[i] < 10000)

        {

             cout << dec << ptr[i]<

        }

        else cout << hex << ptr[i] <<" = " << hex << * ((int*)(ptr[i])) <

    }

    return 0;

}


最后一段话很重要:那就是 各个编译器运行的关于虚继承的结果不一样,很简单,他们处理虚表的机制不一样,但是有一点可以肯定的是,虚继承就是为了解决菱形继承中,B,C都继承了A,D继承了B,C,那么D关于 A的引用只有一次,而不是 普通继承的 对于A引用了两次……

所以上面分析的都是浮云 没用的东西

阅读(703) | 评论(0) | 转发(0) |
0

上一篇:C++多态实现机制

下一篇:C++中友元详解

给主人留下些什么吧!~~