指针和对象切片

时间:2013-06-05 03:19:29

标签: c++ pointers object-slicing

我正在学习关于对象切片的艰难方法,我想知道指针是否有可能被对象切片。换句话说:

  • 指针是否可能成为对象切片的受害者,或者只要您使用指针,您是否总是可以避免对象切片?

2 个答案:

答案 0 :(得分:12)

这取决于你愿意定义“切片”的程度。从某种意义上说,当您使用基指针(或引用)指向派生对象时,任何非虚函数都会被切片。例如:

class A {
    void Print() { cout << "Class A\n"; }
};

class B : public A {
    void DoB() {}
    void Print() { cout << "Class B\n"; }
};

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而不是{ {1}}。

这个问题的一个重要例子与你的析构函数一起发挥作用:

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的析构函数不会被调用。

答案 1 :(得分:3)

是的 - 指向base的指针需要能够引用从base派生的任何类型的对象,并且仍然保留派生对象的正确类型(以及它的价值) ,参考文献也是如此。