动态类型的含义 > 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
只调用classB
的赋值运算符(这是*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);