指针和对象切片

Jas*_*ado 2 c++ pointers object-slicing

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

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

Ric*_*son 13

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

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"
Run Code Online (Sandbox Code Playgroud)

调用DoB不起作用因为我们正在使用指向a的指针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!
Run Code Online (Sandbox Code Playgroud)

这里,因为析构函数没有被标记为virtual,所以它在非虚拟上下文中调用基类的析构函数,这意味着B不会调用析构函数.