На основе диапазона для цикла с абстрактным классом в качестве объявления C ++ - PullRequest
0 голосов
/ 14 января 2019

Я хочу перебрать список абстрактного класса list<abstract>, используя цикл for.

Вот мой код:

class Component {
    protected:
        string name;
        int price;

    public:
        Component(string name, int price): name(name), price(price){};

        virtual int getPrice() =0;
};

class Composite : public Component {
    list<Component> components;

    public:
        int getPrice() {
            for(Component comp : components) {
                return comp.getPrice();   
            } 
        }   
};

class Leaf : public Component {
    public:
        int getPrice() {
            return price;
        }
};

Но я получаю ошибку; не может выделить объект абстрактного типа «Компонент». Эта ошибка имеет смысл, поскольку абстрактные типы не могут быть созданы.

Ответы [ 3 ]

0 голосов
/ 14 января 2019

Ваш код имеет некоторые проблемы:

Вы объявляете virtual int getPrice() = 0;, и это делает ваш Component чисто виртуальным -> вы НЕ МОЖЕТЕ создать экземпляр этого объекта -> list<Component> components; НЕ имеет смысла появляться. Пожалуйста, рассмотрите возможность использования list<Component*> (или смарт-указатель) вместо!

Диапазон для цикла:

for(Component comp : components) {
    return comp.getPrice();   
}

Предположим, вы обновили свой список до list<Component*>, тогда цикл for может быть:

for(auto& comp : components) {
    return comp->getPrice();   
}
0 голосов
/ 14 января 2019

list<Component> означает, что list может содержать только объекты, тип которых точно равен Component. Он не может содержать объекты какого-либо другого типа (даже если он получен из компонента).

Поскольку невозможно создать (завершить) объекты типа Component, этот список нельзя использовать.

Чтобы создать список, в котором может храниться любой объект, имеющий Component в качестве базового класса, элементы списка должны храниться по ссылке. Но тогда вам нужно подумать об управлении временем жизни объектов в списке.


Один из способов сделать это будет:

std::list< std::shared_ptr<Component> > components;

и цикл может быть:

for(auto& comp : components) {
     return comp->getPrice();   
} 

(хотя почему вы используете цикл, когда всегда выходите из первого элемента, это другой вопрос).

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

0 голосов
/ 14 января 2019

Вы должны указать, что вы хотите ссылку:

for(Component & comp : components)

Или просто

for(auto & comp : components)

Если вы хотите (или нуждаетесь), вы также можете добавить модификатор const.

for(const Component & comp : components)

Примечание

Хотя мой ответ может быть неполным, он объясняет ошибку, о которой сообщалось в вопросе. Как и другие не сообщили, нет смысла создавать список абстрактных объектов по значению.

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

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