动态类型的含义 > C++标准称“……虚函数调用的解释取决于它调用的对象的类型(动态类型)”(p 252),然后

动态类型的含义 > C++标准称“……虚函数调用的解释取决于它调用的对象的类型(动态类型)”(p 252),然后,c++,dynamic,types,C++,Dynamic,Types,“如果静态类型为‘指向B’的指针p指向从B派生的D类对象,则*p的动态类型为D”(第2页)。这里,B是基类,D是派生类 这似乎暗示(对我来说)如果我说 D d; B *p = new B(); *p = d; 然后,如果f()在B中是虚拟的,p->f()应该调用D::f(),这是错误的。我想我不清楚“指向类对象…”的含义。我知道,如果我说p=&d,那么就会调用d::f(),但我想知道为什么上面的说法是错误的 D d; B *p = new B(); *p = d; 最后一行将d分配

“如果静态类型为‘指向
B
’的指针
p
指向从
B
派生的
D
类对象,则
*p
的动态类型为
D
”(第2页)。这里,
B
是基类,
D
是派生类

这似乎暗示(对我来说)如果我说

D d; 
B *p = new B(); 
*p = d; 
然后,如果
f()
B
中是虚拟的,
p->f()
应该调用
D::f()
,这是错误的。我想我不清楚“指向类对象…”的含义。我知道,如果我说
p=&d
,那么就会调用
d::f()
,但我想知道为什么上面的说法是错误的

D d; 
B *p = new B(); 
*p = d;
最后一行将
d
分配给
*p
。这意味着它将使用
B
赋值操作符复制
D
实例,对象将被复制。在这种情况下,
*p
的动态类型仍然是
B

p = &d;

将指向
D
对象的指针指定给
p
。在这种情况下不会发生切片,因为您只是分配指针,而不是对象本身。在这种情况下,动态类型<代码> *P<代码>是代码> d>代码> .< /p> 答案的关键是C++中的动态类型永远不会改变。您认为赋值表达式
*p=d
以某种方式将
*p
处的对象完全替换为对象
d
。但事实并非如此。在C++中,对象永远不能真正替换另一个对象。 由于涉及类类型,
*p=d
只调用class
B
的赋值运算符(这是
*p
的静态类型),并带有一个参数
d
。C++中的对象只能被操作,它不能真正被“替换”。 当然,我们谈论复制对象、分配对象等。但这只是为了方便起见,因为大多数情况下,非常精确的语义并不重要,将
=
看作是将一个对象分配给另一个对象很简单。但在本质上,它要么是对目标对象的函数调用(对于类类型),要么是将某些位的值复制到目标对象的空间(对于基本类型)。目标对象本身始终保持不变。

正如塔坦拉玛在上文中所说,在第三行中,您“错误地”将d指定给p所指的对象,因此我们称之为切片。从专业C++,

…向上投射时,使用超类的指针或引用以避免切片

这意味着正确的代码的计算结果与下面的代码相同

D d;
B *p = new B();
p = &d;

D;
B*p=新的B();
p=静态铸件和d;

因此,p(*p)所指对象的动态类型仍然是D。这允许您通过向上或向下投射指向子类而不是对象的指针,在继承层次结构中来回切换。

您至少可以提到您的“正确”代码泄漏内存。不过,谢谢,如果我向D添加一个(公共)成员int a=1;然后是D;B*p=新的B();p=&d;int aa=p->a;这不会编译(g++),即使*p应该是D.@JKay,这是因为
*p
的静态类型是
B
。编译器不知道动态类型,因此
p->a
无效。
D d;
B *p = new B();
p = &d;
D d;
B *p = new B();
p = static_cast<B*>(&d);