cppstruct Base { int b; }; struct Derived : Base { int d; }; Derived dv; Base* pb = &dv; Derived* pd = static_cast<Derived*>(pb);
pb 不能访问变量 d ,pb->b 可以,访问 b 可以
cpp
pb->b = 1; // OK,改的就是 dv.b
pb->d = 2; // 编译错误:'struct Base' has no member named 'd'
原因很简单:成员访问只看静态类型 。pb 的静态类型是 Base*,编译器只认 Base 里声明的成员,而 Base 只有 b。运行时的实际类型是 Derived 这一点,对普通数据成员访问没有任何影响。
几点补充
-
pb->b和dv.b访问的是同一块内存(Base 子对象),互相可见:cpppb->b = 1; assert(dv.b == 1); -
想通过
pb访问d,必须先做转换 ,把静态类型改回Derived*:cppstatic_cast<Derived*>(pb)->d = 2; // 前提:pb 确实指向 Derived 对象 -
虚函数是唯一的"例外" :如果
Base有虚函数,pb->f()会按对象的动态类型分派到Derived::f()。但数据成员没有虚机制,不存在"虚成员变量",所以pb->d永远不会合法。 -
换成
Base b; Base* p = &b;也一样 :p->b合法,p->d编译不过。区别只在于,此时即使强转成Derived*再访问d也是 UB ,因为对象本身不是Derived。