c++问:一般normal derived class &
作出解释
class A
...{
public:
int i;
};
class B1:virtual public A
...{
};
class B2:virtual public A
...{
};
class C2:public B1,public B2
...{
};

int _tmain(int argc, _TCHAR* argv[])
...{
cout << sizeof(A)<< endl; // 4
cout << sizeof(B1)<< endl; // 8
cout << sizeof(C2)<< endl; // 12
C2* pc = new C2();
A* pa = static_cast<A*>(pc);
B1* pb1 = static_cast<B1*>(pc);
B2* pb2 = static_cast<B2*>(pc);
cout << pc << endl; // forexample 002a9728
cout << pa << endl; // 002a9730
cout << pb1 << endl; // 002a9728
cout << pb2 << endl; // 002a972C
int c;
cin >> c;
return 0;
} 从代码可以看出c的内存结构如下(12bit)
------
B1的内容
4bit 指针指向C
------
B2的内容
4bit 指针指向C
-------
C的内容
4bit 保存一个int
------
可以这样去理解
sizeof(A) is 4,这是i的空间,sizeof(b1) is 8,一个4bytes指向A的base指针+4byte的i
有人说pc和pb1的指向同一内存地址?我们可以用下面的想法理解
class A
...{
public:
int i;
};
class B1:virtual public A
...{
public:
int i;
};
class B2:virtual public A
...{
public:
int i;
};
class B3: public A
...{
public:
int i;
};
class B4: public A
...{
public:
int i;
};
class C1:public B1,public B2
...{
public:
int i;
};
class C2: public B3,public B4
...{
public:
int i;
};

int _tmain(int argc, _TCHAR* argv[])
...{
cout << sizeof(A) << endl; // 4
cout << sizeof(B1) << endl; // 12
cout << sizeof(B3) << endl; // 8
cout << sizeof(C1) << endl; // 24
cout << sizeof(C2) << endl; // 20
}


其中A的内存结构
sizeof(A) == 4
----
1~4:A::i --- 4word
----
B1的内存结构(same as B2)
sizeof(B1) == 12
-----
1~4: B1::A* 编译器产生的指向父类的指针因为虚继承指向父类的指针4word也
5~8: B1::i int 4 word
9~12:B1对象中的基类A的内容
----
C1的内存结构
sizeof(C1) == 24
----
(1~8是C1中的B1对象)
1~4: B1::A* 编译器产生的指向父类的指针因为虚继承指向父类的指针4word也
5~8: B1::i int 4 word
(9~16是C1中的B2对象)
9~12: B2::A* 编译器产生的指向父类的指针因为虚继承指向父类的指针4word也
12~16: B2::i int 4 word
(16~20是c1中的数据部分)
16~20 C1::i 4 word
(20~24是C1中的A)
20~24 A::i 4 word
----
我们看如果
B1* pb1 = new B1();
A* pa = static_cast<A*>(pb1);
会发生什么。
首先编译器会找到pb1的对象,把pb1对象的1
如果
B1* pb1 = new C1();
A* pa = static_cast<A*>(pb1);
编译器也会进行相同的操作,并且指向正确位置(虽然偏移的地址量不
接下来我们可以看普通继承
B3的内存分布(B4类似)
sizeof(B3)8
----
(1~4为B3中的A)
1~4 A::i
(5~8)
5~8 B3::i
----
C2的内存分布
sizeof(C3)16
----
(1~4为B3中的A)
1~4 A::i
(5~8)
5~8 B3::i
(9~12为B4中的A)
9~12 A::i
12~16 B4::i
17~20 C2::i
----
大家可以看到如果不使用虚继承C2对象里面有2个A对象
C2* c2 = new C2();
A* pa = static_cast<A*>(c2);
但是我们可以看到下面代码合法
C2* c2 = new C2();
B3* pb1 = static_cast<B3*>(c2);
B4* pb2 = static_cast<B4*>(c2);
A* paOfB3 = static_cast<A*>(pb1);
A* paOfB4 = static_cast<A*>(pb2);
注意paOfB3 != paOfB4.
按照C2内存分配的原则(paOfB4 - paOfB3) == 8
明白了。呵呵?
附小欣欣的解释还有我的跟贴
这是由于c++支持多重继承而引起的某些问题,例如
class A{
public:
void foo();
};
class B: public A{
};
class C: public A{
};
class D: public B, public C{
};
D *p = new D();
p->foo();
这是会触发编译错误,大体是因为有两个可供选择而不能作出决断的
需要将普通集成改为虚拟继承。
D *p = new D();
p->C::foo(); // equal to p->C::A::foo();
p->B::foo();//equal to p->B::A::foo();
ps: 可能有些错误,但大体应该没错
本文详细探讨了C++中虚继承与普通继承的区别,通过具体的内存布局实例对比两种继承方式下对象内存分配的不同,帮助读者深入理解虚继承如何解决多继承带来的二义性问题。

1294

被折叠的 条评论
为什么被折叠?



