c++问:一般normal derived class &
作出解释
... {
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的指向同一内存地址?我们可以用下面的想法理解
... {
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: 可能有些错误,但大体应该没错