如何将 Parent* 对象(指向 &Child 对象)插入到向量中<Child>?



我提供了一个极其简化的代码版本,它再现了错误。

class Shape {
    public:
        virtual void func()=0;
};
class Circle : public Shape {
    public:
        Circle() {  }
        void func() { }
};
class Square : public Shape {
    public:
        Square() {  }
        void func() { }
};
int main() {
    Circle c;
    std::vector<Circle> circs;
    std::vector<Shape*> shapes;
    shapes.push_back(&c);
    circs.push_back(shapes[0]); //ie, the Circle object that was just pushed into the 'shapes' vector.
}

我知道,到目前为止,这在功能上是无用的,我可以只是将Circle对象推到向量上-然而,为了与形状类比保持一致,我的项目也有三角形,正方形等。我使用一个接受Shape&作为参数的函数来处理数据,这样我就可以将所有形状发送到一个函数,而不是为每个形状单独发送函数。这不是重点,但可以让我深入了解为什么我要在简化的代码中做这些事情。

这段代码的最后一行不起作用。谁能告诉我为什么?或者为我提供一个解决方案/解决方案?这被认为是糟糕的编程风格吗?

编辑:所以我已经解决了我所拥有的对象切片问题。对于任何有同样问题的人,看看fgp在以下线程中的答案:

什么是对象切片?

我使用以下内容来帮助允许我尝试做的事情(将Circle对象移动到Shape*,计算一些东西,然后将圆圈(在Shape*向量中)推到其最终休息位置,Circle向量:

class Shape {
public:
    virtual Shape& operator=(const Shape& s) {
        assign(s);
        return *this;
    }
    virtual std::string getName() = 0;
    virtual         int getEdges() = 0;

protected:
    std::string name;
    int         edges;
    void assign(const Shape& s) {
        this->name = s.name;
        this->edges = s.edges;
    }
};
class Circle : public Shape {
private:
    int radius;
public:
    Circle() { name = "Circle"; edges = 1; }
    Circle(int rad) { name = "Circle"; edges = 1; radius = rad; }
    virtual Circle& operator=(const Shape& s) {
        if (const Circle* c = dynamic_cast<const Circle*>(&s))
            assign(*c);
        else{
            std::cout << "BAD ASSIGNMENT IN CIRCLE.";
                    //THROW ERROR HERE INSTEAD OF THE ABOVE COUT
            }
        return *this;
    }
    std::string getName() { return name; }
            int getEdges() { return edges; }
            int getRadius() { return radius; }
           void setRadius(int r) { radius = r; }
protected:
    void assign(const Circle& c) {
        Shape::assign(c);
        this->radius = c.radius;
    }
};
int main() {
    std::vector<Shape*> shapes;
    std::vector<Circle> circs;
    Circle c2(5); //Creates a circle with 5 for the radius.
    shapes.push_back(&c2); //Pushing the 5-radius circle into the Shapes* vector
    Circle c3; //Creates a circle with default constructor (which does NOT define radius)
    c3 = *shapes[0]; //Now, the overloaded assignment operator. Look at Circle::assign(const Shape&) function
    circs.push_back(c3); //We push our newly assigned circle to our Circle vector
    std::cout << "c3 radius: " << circs[0].getRadius(); //This will be 5!
}

看到这个作品真是一个惊喜!c3现在将知道c2的半径,这表明重载赋值操作符适用于Shape -> Circle转换。

如果有人有什么建议,请告诉我!(我将创建一个Circle构造函数,它接受一个(const Shape&)参数,所以我可以使用Circle c = *shapes[0],而不必分开行,因为它找不到接受该参数的构造函数)。

EDIT2:另外,如果你使用这个,确保你throw一个错误(我在你应该的地方留下了注释)。

按照您的意愿进行向下强制转换通常是一个坏主意。但是要直接回答这个问题:

Circle* t = dynamic_cast<Circle*>(shapes[0]);
if(t) //make sure dynamic cast succeeded
  circs.push_back(*t);

必须将引用强制转换为Circle类型,因为它是Shape。

正如我之前提到的,这不是理想的。你真正应该做的是允许你的代码在多态原则下工作。充分利用抽象基类!否则,这可能会导致未定义的行为,特别是当形状在更现实的代码中可能存储的不仅仅是圆圈时。

虽然一个类是从另一个类派生出来的,但它们仍然是两种不同的类型,因此创建基类对象的vector与创建派生对象的vector是不同的。

从设计的角度来看(我强烈推荐),您可以存储指向基类的指针向量,并让虚多态性完成它的工作:使用指向基类的指针向量,而不是引用


编辑:既然你让我在设计概念上再扩展一点,这就是我的想法:

#include <iostream>
#include <vector>
using namespace std;
class Shape {
    protected:
        Shape() {} // Having a protected constructor only allows you to
                   // call it from the same or derived class
    public:
        virtual void func()=0;
};
class Circle : public Shape {
    public:
        Circle() {  }
        void func() { cout << "Hello from a Circle object" << endl; }
};
class Square : public Shape {
    public:
        Square() {  }
        void func() { cout << "Hello from a Square object" << endl; }
};
int main() {
    std::vector<Shape*> shapes;
    Circle c;
    Square s;
    shapes.push_back(&c); // Store the address of the object
    shapes.push_back(&s); // Store the address of the object
    // A call through a pointer to a virtul polymorphic class
    // will make sure to call the appropriate function
    shapes[0]->func(); // Hello from a circle object
    shapes[1]->func(); // Hello from a square object
}
http://ideone.com/X52GLa

是运行时多态性的一个例子,其中只存储基类指针的向量。注意受保护的构造函数:它阻止你直接在派生类之外实例化Shape对象。

相关内容

最新更新