Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Повторное использования кода, Реализация небинарного дерева 
:(
    Опции темы
VictorOff
Дата 19.1.2012, 12:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 22
Регистрация: 6.8.2007

Репутация: нет
Всего: нет



Уважаемые знатоки! 
Требуется ваш совет в области повторного использования кода.
Имеется класс небинарного дерева и класс его узлов. (Пусть будет TBaseTree и TBaseTreeNode) Там реализован весь функционал относящийся к деревьям (построение, поиск, и т.д.)
Теперь у меня есть класс с дополнительным функционалом (пусть будет TMyTree и TMyTreeNode). Как быть? Если я унаследую его от TBaseTree, то все его функции типа Childs, Find и т.д. возвращают TBaseTreeNode. 
Код

TBaseTreeNode * __fastcall TBaseTreeNode::Childs()

и мне придется всюду использовать приведение к TMyTreeNode, что неудобно. 
Перебрав различные варианты (в том числе и субклассирование) я остановился на следующем:
В качестве базового класса использую шаблонный класс 
Код

template <class T> class TBaseTreeNode

а параметр T использую для получения значений в функциях типа Childs 
Код

template <class T> T* __fastcall TMyTreeNode <T>::Childs()

TMyTreeNode наследую от TBaseTreeNode с передачей в параметр своего класса
Код

class TMyTreeNode: public TBaseTreeNode < TMyTreeNode >

Выбранный вариант устраивал до тех пор, пока не понадобился интерфейс класса TBaseTree.
(это надо чтоб в определенном модуле программы объявить переменную с типом абстрактного интерфейса IBaseTree, а передавать в него объекты различных вариантов реализации TMyTreeNode1, TMyTreeNode2…)
При работе с параметризированным классом TBaseTree это невозможно. Был бы очень благодарен, если кто-нибудь поделился дельным советом. 

PM MAIL   Вверх
xvr
Дата 19.1.2012, 13:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(VictorOff @  19.1.2012,  12:01 Найти цитируемый пост)
Выбранный вариант устраивал до тех пор, пока не понадобился интерфейс класса TBaseTree.
(это надо чтоб в определенном модуле программы объявить переменную с типом абстрактного интерфейса IBaseTree, а передавать в него объекты различных вариантов реализации TMyTreeNode1, TMyTreeNode2…)

А как вы потом разберетесь какая именно реализация к вам пришла?

Цитата(VictorOff @  19.1.2012,  12:01 Найти цитируемый пост)
При работе с параметризированным классом TBaseTree это невозможно.

Делаете интерфейс IBaseTree, и наследуете шаблонный класс TBaseTree от него. Таким образом IBaseTree (не шаблонный) станет родителем всех шаблонных производных от TBaseTree (что вам собственно и надо)

PM MAIL   Вверх
VictorOff
Дата 19.1.2012, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 22
Регистрация: 6.8.2007

Репутация: нет
Всего: нет



Цитата

Делаете интерфейс IBaseTree, и наследуете шаблонный класс TBaseTree от него. Таким образом IBaseTree (не шаблонный) станет родителем всех шаблонных производных от TBaseTree (что вам собственно и надо)


А можно поконкретнее?
Ранее у меня было
Код

template<class T> class TBaseNode
{
public:
    virtual T* __fastcall FirstChild() {return NULL;}
};
//---------------------------------------------------------------------------

class TMyNode : public TBaseNode<TMyNode>
{
public:
    void __fastcall MyFunction() {;}
};

TMyNode *MyNode;
...
TMyNode *MyChildNode=MyNode->FirstChild();
MyChildNode->MyFunction();

хотелось бы иметь возможность что-то вроде
Код

class IBaseNode
{
    virtual IBaseNode* __fastcall FirstChild()=0; //IBaseNode*?!
}; 
TMyNode *MyNode;
...
IBaseNode *BaseNode = MyNode;    

но как реализовать данный вариант? Это не работает.
Код

template<class T> class TBaseNode : public IBaseNode
{
public:
    virtual T* __fastcall FirstChild() {return NULL;}
};
//---------------------------------------------------------------------------

class TMyNode : public TBaseNode<TMyNode>
{
public:
    void __fastcall MyFunction() {;}
};


Следовательно, использование параметризированного класса TBaseNode не лучший вариант, если требуется работа с интерфейсом и необходима к.л. другая конструкция?
PM MAIL   Вверх
xvr
Дата 19.1.2012, 17:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(VictorOff @  19.1.2012,  14:37 Найти цитируемый пост)
но как реализовать данный вариант? Это не работает.

Именно так. Почему не работает? В смысле не дает перегрузить FirstChild() ? Сделайте так:
Код

class IBaseNode
{
virtual IBaseNode* __fastcall real_FirstChild()=0;
};

template<class T> class TBaseNode : public IBaseNode
{
public:
virtual IBaseNode* __fastcall real_FirstChild() {return NULL;}
T* __fastcall FirstChild() {return real_FirstChild();}
};

class TMyNode : public TBaseNode<TMyNode>
{
public:
void __fastcall MyFunction() {;}
};


PM MAIL   Вверх
VictorOff
Дата 20.1.2012, 08:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 22
Регистрация: 6.8.2007

Репутация: нет
Всего: нет



Цитата

Именно так.

Код

class IBaseNode
{
public:
    virtual IBaseNode* __fastcall real_FirstChild()=0;
};
//---------------------------------------------------------------------------

template<class T> class TBaseNode : public IBaseNode
{
public:
    virtual IBaseNode* __fastcall real_FirstChild() {return NULL;}
    T* __fastcall FirstChild() {return real_FirstChild();}
};
//---------------------------------------------------------------------------

class TMyNode : public TBaseNode<TMyNode>
{
public:
    void __fastcall MyFunction() {;}
};

Просто хотелось как-то поизящнее, если уж так, то можно сразу обойтись без шаблона
Код

class IBaseNode
{
public:
    virtual IBaseNode* __fastcall real_FirstChild()=0;
};
//---------------------------------------------------------------------------

class TBaseNode : public IBaseNode
{
public:
    virtual IBaseNode* __fastcall real_FirstChild() {return NULL;}
};
//---------------------------------------------------------------------------

class TMyNode : public TBaseNode
{
public:
    void __fastcall MyFunction() {;}
    virtual TMyNode* __fastcall FirstChild() {return static_cast<TMyNode*>(real_FirstChild());}
};

Немного не коробит, что при вызове через интерфейс необходимо использовать одно наименование метода, а в TMyNode другое?
PM MAIL   Вверх
xvr
Дата 20.1.2012, 12:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(VictorOff @  20.1.2012,  08:24 Найти цитируемый пост)
Просто хотелось как-то поизящнее, если уж так, то можно сразу обойтись без шаблона

Так вам придется определять FirstChild в каждом конечном наследнике.

Цитата(VictorOff @  20.1.2012,  08:24 Найти цитируемый пост)
Немного не коробит, что при вызове через интерфейс необходимо использовать одно наименование метода, а в TMyNode другое? 

Увы, ваш IBaseNode слишком generic, что бы в нем можно было найти общий базовый класс для возврата из FirstChild(). У вас фактически каждый TBaseNode<> реализует свое дерево (по типу аргумента шаблона). И на уровне самого шаблона TBaseNode нет никакой связи между типом T и IBaseNode

PM MAIL   Вверх
VictorOff
Дата 20.1.2012, 13:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 22
Регистрация: 6.8.2007

Репутация: нет
Всего: нет



xvr, согласен, вы правы, спасибо.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0578 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.