C ++ Переопределенный метод не вызывается - PullRequest
10 голосов
/ 18 сентября 2009

Shape.h

namespace Graphics {
    class Shape {
    public:
        virtual void Render(Point point) {};
    };
}

Rect.h

namespace Graphics {
    class Rect : public Shape {
    public:
        Rect(float x, float y);
        Rect();
        void setSize(float x, float y);
        virtual void Render(Point point);

    private:
        float sizeX;
        float sizeY;
    };
}

struct ShapePointPair {
    Shape shape;
    Point location;
};

Используется так:

std::vector<Graphics::ShapePointPair> theShapes = theSurface.getList();

for(int i = 0; i < theShapes.size(); i++) {
    theShapes[i].shape.Render(theShapes[i].location);
}

Этот код вызывает Shape::Render, а не Rect::Render

Я предполагаю, что это потому, что он приводит Rect к Shape, но я понятия не имею, как это остановить. Я пытаюсь позволить каждой фигуре управлять тем, как она отображается, переопределяя метод Render.

Есть идеи, как этого добиться?

Ответы [ 8 ]

22 голосов
/ 18 сентября 2009

Вот ваша проблема:

struct ShapePointPair {
        Shape shape;
        Point location;
};

Вы храните Shape. Вы должны хранить Shape * или shared_ptr<Shape> или что-то еще. Но не Shape; C ++ не является Java.

Когда вы присваиваете Rect для Shape, копируется только часть Shape (это нарезка объекта ).

4 голосов
/ 18 сентября 2009

Эта проблема называется нарезкой - вы теряете производную функциональность при копировании в базу. Чтобы избежать этого, используйте указатели на базовый класс, т.е.

std::vector<Graphics::Shape*> s;
s.push_back(&some_rect);
2 голосов
/ 18 сентября 2009

Проблема в том, что в вашем векторе вы храните копии объектов Shape, а копирование объекта Shape не копирует данные или функциональные возможности его производных классов - вы нарезаете полиморфизм.

Управляйте объектами, используя new и delete, и организуйте, чтобы ваш вектор сохранял указатели на них.

1 голос
/ 18 сентября 2009

Вы обращаетесь к объекту формы непосредственно для переопределения, чтобы работать, вам нужно получить доступ к объекту через указатель или ссылки.

Например, когда вы назначаете Shape в ShapePointPair, код «срезает» объект и копирует только бит Shape в ShapePointPair

Это будет означать, что вам нужно следить за управлением памятью, чтобы вы могли использовать умный указатель в структуре. ShapePointPair { форма smart_pointer; Местоположение точки; };

1 голос
/ 18 сентября 2009

Полиморфизм будет работать только от указателя на форму, а не от объекта формы.

0 голосов
/ 05 декабря 2018

Я не уверен, что объясню хорошо, потому что мой английский плохой.

Я думаю, вы должны использовать его как ссылку или тип указателя. потому что форма точно определена, что она должна делать.

Если вы используете свой код напрямую, ваш ребенок попытается скопировать и выполнить работу фигуры. Вот почему не работает ваша функция переопределения.

использовать указатель или ссылку как это.

pointer.h

class Parent {
public:
    virtual void work() { printf("parent is working now\n"); }
};
class Child1 {
public:
    virtual void work() { printf("child1 is working now\n"); }
};
class Child2 {
public:
    virtual void work() { printf("child2 is working now\n"); }
};
struct Holder {
    Parent* obj1;
    Parent* obj2;
};
int main() {
    Child1 child1;
    Child2 child2;
    Holder holder = { &child1, &child2 };
    holder.obj1->work();
    holder.obj2->work();
    return 0;
}

reference.h

class Parent {
public:
    virtual void work() { printf("parent is working now\n"); }
};
class Child1 {
public:
    virtual void work() { printf("child1 is working now\n"); }
};
class Child2 {
public:
    virtual void work() { printf("child2 is working now\n"); }
};
struct Holder {
    Parent& obj1;
    Parent& obj2;
};
int main() {
    Child1 child1;
    Child2 child2;
    Holder holder = { child1, child2 };
    holder.obj1.work();
    holder.obj2.work();
    return 0;
}

* ps: лично я использую абстрактную функцию (virtual void что-то () = 0;). потому что я тоже иногда забывал об этом, поэтому я улавливаю это как синтаксическую ошибку.

0 голосов
/ 18 сентября 2009

Вы можете попробовать повысить :: ptr_vector

http://www.boost.org/doc/libs/1_40_0/libs/ptr_container/doc/ptr_container.html

0 голосов
/ 18 сентября 2009

Нет, это не кастинг.

Вместо этого вы можете сохранить ссылку на базовый класс. Точка:

struct ShapePointPair {
        Shape shape;
        Point &location;
};

Эта ссылка должна быть установлена ​​во время построения структуры ShapePointPair. Добавьте конструктор в ShapePointPair для этого цель. Должны быть переданы (вновь созданные) экземпляры Rect.

Также соблюдайте обязанности по управлению памятью (собственно письменные деструкторы и пр.).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...