2014-11-19 1 views
2

Could (Редактировать: Должен) Я делаю что-то вроде этого?Должен ли я наследовать вложенный класс внутри производного класса в C++?

Edit:

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

template<typename T> 
class Tree { 
protected: 
    class Node { 
     Node* _parent; 
     T _data 
    }; 
}; 

template<typename T> 
class BinaryTree: public Tree { 
private: 
    class BinaryNode: public Tree<T>::Node { 
     Node *_left, *_right; 
    }; 
}; 
+0

попробовать? Просто сделайте Iterator общедоступной, теперь она приватная. Также может потребоваться List :: Iterator. – 0xbaadf00d

+0

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

+0

Я отредактирую это немного ... – Dori

ответ

0

Этот способ построения параллельных иерархий классов не является чем-то необычным. Однако чаще всего скрывать вложенный производный класс в качестве детали реализации, который должен быть инкапсулирован, т. Е. BiIterator в вашем примере будет находиться в разделе private:.

Однако Iterator не является хорошим примером из объекта нарезка: даже если BiIterator остается общественности, это, казалось бы, невинный код неверен:

BidirectionalList biList; 
// This would slice off BiIterator's functionality 
Iterator iter(biList.get_iterator()); 
while (iter.has_next()) { 
    ... 
} 

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

class Task { 
public: 
    class Worker { 
     public virtual void work()=0; 
    } 
    void run(Worker& w); 
}; 
class SpecialTask : public Task { 
private: 
    class SpecialWorker : public Worker { 
     public virtual void work() { 
      ... 
     } 
    }; 
public: 
    void do_something() { 
     SpecialWorker w; 
     run(w); // Passes SpecialWorker to run() of base class 
    } 
}; 
+0

В вашем примере неправильного кода: зачем мне это делать? Если у меня есть двунаправленный список, я бы использовал «BiIterator», а не «Итератор», поэтому не было бы нарезки ...? – Dori

+0

@Dori Это хороший вопрос: вы сделали бы это, если не хотите каких-либо дополнительных функций от вашего «BiIterator», только функциональность от «Итератора». Это называется «программирование для интерфейса». – dasblinkenlight

+0

Итак, когда я хочу запрограммировать интерфейс без нарезки?Когда я * не * хочу обрезать 'BiIterator', если я делаю * не * хочу добавить функциональность? – Dori

0

Там нет ничего противозаконного о том, что вы делаете так, вы может сделайте это.

Но для этого примера я считаю, что ответ ясен. При реализации контейнеров на C++ они решили реализовать iterator отдельно от всех своих классов контейнеров. Выгода от их мудрости не будет плохим выбором в этом случае.

EDIT:

Для контейнера структуры вашего содержащийся типа объекта должен быть Шаблонной. Для моего доказательства я снова обратился к дизайну контейнера C++.

Но здесь я думаю, что это намного более четкое сокращение. Если вы напишете отличный Tree или BinaryTreeclass, который является темплатированным, вы можете использовать его снова и снова во всем коде, который вы пишете всю оставшуюся жизнь. Почему бы не воспользоваться этим?

(Просто слово предостережения вы могли бы изобретать колесо здесь Взгляните на это:. http://www.cplusplus.com/reference/algorithm/make_heap/)

+0

Обновленный мой пример, вы могли бы взглянуть? – Dori

+0

Разве это не templatized? У 'Node' есть' T' в нем, как и (вложенной наследованием) 'BinaryNode'. Кроме того, это домашнее задание Uni, так что да, я изобретаю колесо :) – Dori

+0

@Dori Да, но я предлагал один контейнер, с набором узлов итерация становится отрывочной. –