C++ - 即使在使用指针后对象切片

C++ - Object slicing even after using pointers

我有一个基础 class Shape 和一个派生的 class Circle,它公开继承了 Shape:

class Circle : public Shape

我制作了一个 C++ 形状指针向量,并将 Circle 指针分配给它们。我阅读了很多关于对象切片的内容,因此希望代码将向量中的 Circle 视为 Circle,而不是 Shape。

任何人都可以根据输出指出这有什么问题吗?

int main(void) {
vector<Shape*> shapes;

Circle* ncl = new Circle(-8, -8, 0.2f);
shapes.push_back(ncl);

cout << "Expected: " << *ncl << endl;
cout << "Reality: " << *shapes[0] << endl;
}

输出:

Expected: Circle is at: -8,-8 and has a radius of: 0.2
Reality: Shape centered at point: -8,-8

我已经为超出范围的两个 class 覆盖了 << 运算符,所以我认为这不是问题,但仍然 - 这是我覆盖的代码上下文:

inline std::ostream& operator<< (std::ostream& stream, const Shape& shape) {
    std::cout << "Shape centered at point: " << shape.getX() << "," << shape.getY();
    return stream;
}

inline std::ostream& operator<< (std::ostream& stream, const Circle& circle) {
    std::cout << "Circle is at: " << circle.getX() << "," << circle.getY() << 
        " and has a radius of: " << circle.getR();
    return stream;
}

总而言之 - 我希望能够在 Circle 变量存储在 Shape 向量中时正确访问它们(使用指针或其他方式)。

重载决议是用静态类型完成的。

您可以使用:

std::ostream& operator<< (std::ostream& stream, const Shape& shape) {
    shape.print(stream);
    return stream;
}

virtual void Shape::print(std::ostream&) const; 一起解决您的问题。

没有涉及切片,只是看起来像。

重载是在编译时从编译器已知的静态类型select编辑的。
由于 shapesvector<Shape*>*shapes[0]Shape&,因此选择了重载。

常见的解决方案是只为基 class 编写一个 operator<<,然后调用对象上的虚函数。
这将使动态函数在运行时分派 select 函数。

例如:

struct Shape  { virtual ostream& print(ostream& os) const { ... } };
struct Circle { ostream& print(ostream& os) const override { ... } };

ostream& operator<<(ostream& os, const Shape& s) { return s.print(os); }