我正在学习对象切片的艰难方式,我想知道指针是否有可能被对象切片。换句话说:
- 指针是否可以成为对象切片的受害者,或者只要你使用指针,你是否总是安全的?
这取决于你对"切片"的定义有多宽泛。从某种意义上说,当您用基指针(或引用)指向派生对象时,任何非虚函数都会被分割。例如:
class A {
void Print() { cout << "Class An"; }
};
class B : public A {
void DoB() {}
void Print() { cout << "Class Bn"; }
};
B b;
A* a = &b;
a->DoB(); // Won't compile!
a->Print(); // Prints "Class A", not "Class B"
对DoB
的调用不起作用,因为我们使用了指向A
的指针,所以编译器不知道它可以在该指针上调用DoB
。这样,您将失去B
的一部分,因此您可以将其视为切片的一种形式。
最后一行是一个叫做"名字隐藏"现象的例子。因为Print
没有在基类中声明为virtual
,而指针的类型是A
,编译器不知道它应该调用B::Print
而不是A::Print
。
class A {
~A() {}
};
class B : public A {
std::vector<int> v;
};
A* a = new B;
delete a; // What happens to B::v? Undefined behaviour!
在这里,因为析构函数没有标记为virtual
,所以它在非虚拟上下文中调用基类的析构函数,这意味着不会调用B
的析构函数。
是——需要一个指向base
的指针,以便能够引用从base
派生的任何类型的对象,并且仍然保留派生对象的正确类型(并且为了它的价值,引用也是如此)。