如果是多继承,并且 upcast到不同的接口的时候,需要用dynamic_cast
比如,下面的代码,第37行一定要用 dynamic_cast,因为它是从一个 基类接口转到另外一个基类借口。
1 class A
2 {
3 public:
4 virtual bool IsA(void) = 0;
5 protected:
6 int t_a;
7 };
8
9 class B
10 {
11 public:
12 virtual bool IsB( void ) = 0;
13 protected:
14 int t_b;
15 };
16
17 class C: public A, public B
18 {
19 public:
20
21 C(){}
22 ~C(){}
23 bool IsA(void) { return true;}
24 bool IsB(void) { return true;}
25
26 virtual bool isC(void){return true;}
27 private:
28 int m_c;
29 };
30
31 int main(void)
32 {
33 A *pA = new C;
34
35 C * pC = (C*)pA;
36 B *pB = (B*)pA;
37 B *pB2 = dynamic_cast<B*>(pA);
38
39 return 0;
40 }
使用GDB打印变量的值:
(gdb) p pA $2 = (A *) 0x804fa10 (gdb) p pB $3 = (B *) 0x804fa10 (gdb) p pB2 $4 = (B *) 0x804fa18
可以看到,pB 和 pB2的值不一样。
使用命令
clang -cc1 -fdump-record-layouts
打印出类的内存分布:
*** Dumping AST Record Layout
0 | class A
0 | (A vtable pointer)
4 | int t_a
| [sizeof=8, dsize=8, align=4,
| nvsize=8, nvalign=4]
*** Dumping AST Record Layout
0 | class B
0 | (B vtable pointer)
4 | int t_b
| [sizeof=8, dsize=8, align=4,
| nvsize=8, nvalign=4]
*** Dumping AST Record Layout
0 | class C
0 | class A (primary base)
0 | (A vtable pointer)
4 | int t_a
8 | class B (base)
8 | (B vtable pointer)
12 | int t_b
16 | int m_c
| [sizeof=20, dsize=20, align=4,
| nvsize=20, nvalign=4]
可以看到,类B在 C 对象上的偏移为 8, 可以看到,dynamic_cast后的值就是对应的B类的地址。
|