当前位置: 首页 > 工具软件 > Upcast > 使用案例 >

(C++)upcast的时候一定要用 dynamic_cast 吗?

邵崇凛
2023-12-01

如果是多继承,并且 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类的地址。

 类似资料: