2

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

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

2 回答 2

14

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

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不起作用,因为我们使用的是指向 an 的指针A,因此编译器不知道它可以调用DoB该指针。这样一来,您就失去了 的一部分B,因此您可以将其视为一种切片形式。

特别是最后一行是一种称为“名称隐藏”的现象的示例。因为Print没有virtual在基类中声明,而且我们的指针是 type 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不会调用 ' 的析构函数。

于 2013-06-05T04:28:22.183 回答
3

是的 - 需要一个指针才能base引用派生自的任何类型的对象,base并且仍然保留派生对象的正确类型(并且对于它的价值,引用也是如此)。

于 2013-06-05T03:26:03.467 回答