(Возможно, на этот вопрос уже был дан ответ, и я могу найти аналогичный вопросы, но ничего, что я могу применить к моей ситуации. Ссылки на соответствующие вопросы, конечно, приветствуются.)
Вот иллюстрация того, что я пытаюсь сделать:
#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();
… думая, что я мог бы иметь, чтобы это указывало на первый экземпляр в моем векторе. Вот где я в тупике.
Предложения приветствуются!
В C ++ 11
return { begin(vec), end(vec) };
преобразует вектор конкретных указателей в вектор абстрактных. Это так просто.
В C ++ 03 вы должны явно вызывать конструктор и использовать .begin
вместо свободной функции.
Итератор приведения, который переводит итераторы в бетон и производит итераторы в абстракцию, может быть записан либо с помощью повышения, либо вручную, а затем диапазон из упомянутых выше.
Введите стирание итераторов, чтобы они были просто «общими итераторами для abstract*
‘может быть сделано, с наддувом или без. Это увеличивает накладные расходы (которые могут быть существенными, если не сделано тщательно), и их следует развлекать только в том случае, если вышеупомянутые два варианта оказались проблематичными, и это продемонстрировано для устранения проблемы в реальных тестах.