Обработка коллекции указателей на экземпляры производного класса, как если бы они были родительским классом

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

Вот иллюстрация того, что я пытаюсь сделать:

    #include <vector>

class Abstract
{
public:
virtual std::vector<Abstract *> children() = 0;
};

class Concrete : public Abstract
{
public:
std::vector<Abstract *> children() override {return std::vector<Abstract *>();}
/* This returns an empty vector. What should actually go here, to return the actual children? */
private:
std::vector<Concrete *> m_children;
};

void doSomething(Abstract *a)
{

}

int main()
{
Concrete c;

for(auto& object : c.children())
doSomething(object);
}

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

(в аннотации)

virtual std::vector<const Abstract *>::const_iterator begin() const = 0;
virtual std::vector<const Abstract *>::const_iterator end() const = 0;
virtual std::vector<Abstract *>::iterator begin() = 0;
virtual std::vector<Abstract *>::iterator end() = 0;

, но что мне делать в Concrete :: begin () (где m_ children объявлено как

m_children std::vector<Concrete *>

)? Я начал так:

    std::vector<const Abstract *>::const_iterator it;
Abstract *first = *m_children.begin();

… думая, что я мог бы иметь, чтобы это указывало на первый экземпляр в моем векторе. Вот где я в тупике.

Предложения приветствуются!

0

Решение

В C ++ 11

return { begin(vec), end(vec) };

преобразует вектор конкретных указателей в вектор абстрактных. Это так просто.

В C ++ 03 вы должны явно вызывать конструктор и использовать .begin вместо свободной функции.

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

Введите стирание итераторов, чтобы они были просто «общими итераторами для abstract*‘может быть сделано, с наддувом или без. Это увеличивает накладные расходы (которые могут быть существенными, если не сделано тщательно), и их следует развлекать только в том случае, если вышеупомянутые два варианта оказались проблематичными, и это продемонстрировано для устранения проблемы в реальных тестах.

0

Другие решения


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector