Попытка push_back в вектор, указывающий на абстрактный класс

#c #c 11

#c #c 11

Вопрос:

Компиляция моего кода, содержащего этот класс:

 class Dessin
{
    private:
        vector<Figures*>T;
    public:
        void ajouteFigure(const Figuresamp; f) const
        {
            for(auto element: T)
            {
                T.push_back(f);
            }
        }
};
 

выдает ошибку:

[Ошибка] нет соответствующей функции для вызова ‘std::vector::push_back(const Цифрыamp;) const’

Это то, что я должен делать в main()

 Dessin s;
s.ajouteFigure(Cercle(1.1));
 

Почему это не сработает?

Комментарии:

1. @AlexD, хотя и ошибочный с самого начала.

2. Вместо этого не храните необработанные указатели в a std::vector — use std::vector<std::unique_ptr<Figure>> .

3. @AlexD Я пробовал это, это не работает. Та же ошибка

4. @AlexD Это работает, спасибо. Могу ли я узнать, почему именно?

5. Этот код настолько неработающий, что никакой ответ вам не поможет.

Ответ №1:

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

Чтобы «исправить» ошибку, вы должны изменить свой ajouteFigure прототип, чтобы принимать Figures указатели и неконстантные this :

 void ajouteFigure(Figures* f) 
 

Затем вы должны вызвать его, передавая указатель на Figures объект, т.Е. Созданный с new помощью выражения:

 s.ajouteFigure(new Cercle(1.1));
 

При этом этот код кажется бессмысленным. Вы добавляете указатель столько раз, сколько у вас есть элементов в векторе (который всегда равен 0 в приведенном вами примере).

Использование необработанных указателей также не рекомендуется, вы должны использовать интеллектуальные указатели, такие как std::unique_ptr , хотя это нарушило бы текущий код.

Рассмотрим этот, менее неправильный, пример:

 class Dessin
{
    private:
        vector<unique_ptr<Figures>> T;
    public:
        void ajouteFigure(unique_ptr<Figures> f)
        {
            T.push_back(move(f)); // just once
        }
};
 

и на сайте вызова:

 Dessin s;
s.ajouteFigure(make_unique<Cercle>(1.1)); // C  ≥14
 

или, если вы не можете использовать C 14:

 Dessin s;
s.ajouteFigure(unique_ptr<Figures>(new Cercle{1.1}));
 

Комментарии:

1. Этот вопрос помечен как c 11, вероятно, вам следует предоставить альтернативу std::make_unique на случай, если OP еще не использует c 14.

2. Добавлен @Archieposopofbanterbury.

Ответ №2:

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

Таким образом, вам не нужно создавать std::unique_ptr или использовать new каждый раз, когда вы вызываете функцию.

Вот базовая реализация:

 class Dessin{
    public:
        template<typename T, typename ... Args>
        void ajouteFigure(Args amp;amp;... args){
            figures.emplace_back(new T(std::forward<Args>(args)...));
        }

    private:
        std::vector<std::unique_ptr<Figures>> figures;
};
 

Тогда использование класса менее подвержено ошибкам:

 int main(){
    Dessin d;
    d.ajouteFigure<Cercle>(1.1);
}