Вопрос по наследованию
От: NordS  
Дата: 16.10.04 16:56
Оценка:
Есть три класса для хранения структуры меню:


//базовый класс пункта меню
class MenuItemBase
{
public:
    CComBSTR Name;
};

//обыкновенный пункт меню
class MenuItem : public MenuItemBase
{
};

//раскрывающийся пункт меню(еще может содержать MenuItem и MenuGroup)
class MenuGroup : public MenuItemBase
{
public:
    CAtlArray<MenuItemBase> Items;
};



Далее

MenuGroup g;
MenuItem mi;
MenuGroup mg;

g.Items.Add(mi);
g.Items.Add(mg);


И вот тут то встает вопрос, каким образом при получении элемента из массива различать что у меня MenuGroup ли MenuItem?
Re: Вопрос по наследованию
От: yxiie Украина www.enkord.com
Дата: 16.10.04 17:36
Оценка: 1 (1)
Здравствуйте, NordS, Вы писали:

NS>И вот тут то встает вопрос, каким образом при получении элемента из массива различать что у меня MenuGroup ли MenuItem?


if (typeid(obj)==typeid(MenuGroup)) {
    ...
}
... << RSDN@Home 1.1.3 stable >>
Re[2]: Вопрос по наследованию
От: Shady Россия  
Дата: 16.10.04 17:40
Оценка:
Здравствуйте, yxiie, Вы писали:

Y>
Y>if (typeid(obj)==typeid(MenuGroup)) {
Y>    ...
Y>}
Y>


Ню ню Незнаю как на других компиляторах, ну чтоб на msvc врубить RTTD (или как там называется), надо выставить:
Во-первых ключик компилятора
Во-вторых надо чтоб хоть одна функция в классе была виртуальной

Видно, что человек не разбирается в C++, так почему же давать столь скудные ответы?
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
"Man feed machine
Machine feed man"
Peter Gabriel — OVO — The Tower That Ate People
Re[3]: Вопрос по наследованию
От: yxiie Украина www.enkord.com
Дата: 16.10.04 17:46
Оценка:
Здравствуйте, Shady, Вы писали:

S>Видно, что человек не разбирается в C++,


почему ты сделал такой вывод

S>так почему же давать столь скудные ответы?


почему же скудные? ориентир правильный, а тонкости использования RTTI со своим компилятором он поищет в сопутствующей документации к компилятору по ключевому слову typeid
... << RSDN@Home 1.1.3 stable >>
Re[4]: Вопрос по наследованию
От: Shady Россия  
Дата: 16.10.04 17:53
Оценка:
Здравствуйте, yxiie, Вы писали:

Y>почему ты сделал такой вывод

Незнаю, просто такое ощущение, вопрос же простой, человек, подкованный в с++ не стал бы задовать его на рсдн, он бы знал ответ

Y>почему же скудные? ориентир правильный, а тонкости использования RTTI со своим компилятором он поищет в сопутствующей документации к компилятору по ключевому слову typeid

О! RTTI это называется По ключевому слову "typeid" в msdn нет ничего про то, что у класса должна быть хоть одна виртуальная функция (и что RTTI генерируется только для такого класса), там вскольз упоминается, что typeid примяняется для "полиморфных" классов...

Ладно, извени за придирку!
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
"Man feed machine
Machine feed man"
Peter Gabriel — OVO — The Tower That Ate People
Re[5]: Вопрос по наследованию
От: yxiie Украина www.enkord.com
Дата: 16.10.04 20:11
Оценка:
Здравствуйте, Shady, Вы писали:

S>Здравствуйте, yxiie, Вы писали:


S>О! RTTI это называется По ключевому слову "typeid" в msdn нет ничего про то, что у класса должна быть хоть одна виртуальная функция (и что RTTI генерируется только для такого класса), там вскольз упоминается, что typeid примяняется для "полиморфных" классов...


ну нажми F1 на слове typeid, в VC7.0 покажет и какие ключики и все все все...
... << RSDN@Home 1.1.3 stable >>
Re: Вопрос по наследованию
От: MaximE Великобритания  
Дата: 16.10.04 20:50
Оценка: 3 (2)
NordS wrote:

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

>
> //базовый класс пункта меню
> class MenuItemBase
> {
> public:
       virtual CAtlArray<MenuItemBase>* sub_items() = 0;

>     CComBSTR Name;
> };
>
> //обыкновенный пункт меню
> class MenuItem : public MenuItemBase
> {
       CAtlArray<MenuItemBase>* sub_items() { return 0; }
> };
>
> //раскрывающийся пункт меню(еще может содержать MenuItem и MenuGroup)
> class MenuGroup : public MenuItemBase
> {
> public:
       CAtlArray<MenuItemBase>* sub_items() { return &Items; }

>     CAtlArray<MenuItemBase> Items;
> };
>

>
>
> Далее
>
>
> MenuGroup g;
> MenuItem mi;
> MenuGroup mg;
>
> g.Items.Add(mi);
> g.Items.Add(mg);
>

>
> И вот тут то встает вопрос, каким образом при получении элемента из массива различать что у меня MenuGroup ли MenuItem?

void f(MenuItemBase* item)
{
     if(CAtlArray<MenuItemBase>* sub_items = item->sub_items())
     {
         // item имеет дочерние items, сделаем что-то с ними
         sub_items->screw_them_all();
     }
}


--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 gamma
Re: Вопрос по наследованию
От: Quintanar Россия  
Дата: 16.10.04 22:33
Оценка:
Здравствуйте, NordS, Вы писали:

NS>И вот тут то встает вопрос, каким образом при получении элемента из массива различать что у меня MenuGroup ли MenuItem?


А почему бы просто не завести в базовом классе переменную типа union, где хранить тип пункта меню?
Re: Вопрос по наследованию
От: Олег Гашев
Дата: 17.10.04 18:09
Оценка: 3 (2)
Здравствуйте, NordS, Вы писали:

NS>//раскрывающийся пункт меню(еще может содержать MenuItem и MenuGroup)

NS>class MenuGroup : public MenuItemBase
NS>{
NS>public:
NS> CAtlArray<MenuItemBase> Items;
NS>};
NS>[/code]

NS>И вот тут то встает вопрос, каким образом при получении элемента из массива различать что у меня MenuGroup ли MenuItem?


А зачем MenuGroup и MenuItem? Оставь только MenuItem. Если это не раскрывающийся пункт меню, у него Items=NULL; Если это раскрывающийся пункт меню, но не содержащий ни одного элемента, Items!=0, Items.Count=0;
Либо я найду путь, либо проложу его. © Свифт
Re[2]: Вопрос по наследованию
От: MaximE Великобритания  
Дата: 17.10.04 19:09
Оценка:
Олег Гашев wrote:

[]

> А зачем MenuGroup и MenuItem? Оставь только MenuItem. Если это не раскрывающийся пункт меню, у него Items=NULL; Если это раскрывающийся пункт меню, но не содержащий ни одного элемента, Items!=0, Items.Count=0;


Мне часто приходится работать с пустыми меню и я нахожу их крайне удобными

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9 gamma
Re: Вопрос по наследованию
От: _Winnie Россия C++.freerun
Дата: 17.10.04 20:42
Оценка: 1 (1)
Здравствуйте, NordS, Вы писали:

NS>
NS>    CAtlArray<MenuItemBase> Items;
NS>};
NS>

Быстро просмотрел MSDN, кажется, когда ты хранишь в CAtlArray "MenuItemBase", то ты хранишь там только базовый класс, и при добавлении в массив куски производного класса "обрезаются".

Самое простое — это завести виртуальную фунцию "IsMenuGroup", которая будет сообщать, кто там конретный потомок.
Или более красивый код от MaximE.

NS>
NS>//базовый класс пункта меню
NS>class MenuItemBase
NS>{
NS>public:
    virtual bool IsMenuGroup()=0;
NS>    CComBSTR Name;
NS>};

NS>//обыкновенный пункт меню
NS>class MenuItem : public MenuItemBase
NS>{
    virtual bool IsMenuGroup() { return false; }
NS>};

NS>//раскрывающийся пункт меню(еще может содержать MenuItem и MenuGroup)
NS>class MenuGroup : public MenuItemBase
NS>{
      virtual bool IsMenuGroup() { return true; }
NS>public:
NS>



Бррр, не люблю стандартный RTTI. Ограниченный(узнать TypeID? А я хочу его фабрику и список членов. ), тормозной(так как расчитан на все случаи жизни, типа виртуального наследования).
Правильно работающая программа — просто частный случай Undefined Behavior
Re[3]: Вопрос по наследованию
От: Олег Гашев
Дата: 17.10.04 21:55
Оценка:
Здравствуйте, MaximE, Вы писали:

>> А зачем MenuGroup и MenuItem? Оставь только MenuItem. Если это не раскрывающийся пункт меню, у него Items=NULL; Если это раскрывающийся пункт меню, но не содержащий ни одного элемента, Items!=0, Items.Count=0;


ME>Мне часто приходится работать с пустыми меню и я нахожу их крайне удобными


Интересно чем?

MenuGroup ведёт себя как MenuItem, отличие только в наличии субменю. Поэтому MenuGroup можно убрать. Items сделать как readonly. Если MenuItem имеет субменю, у него Items!=NULL.
Либо я найду путь, либо проложу его. © Свифт
Re[4]: Вопрос по наследованию
От: LaptevVV Россия  
Дата: 18.10.04 04:49
Оценка:
Здравствуйте, Олег Гашев, Вы писали:

ОГ>MenuGroup ведёт себя как MenuItem, отличие только в наличии субменю. Поэтому MenuGroup можно убрать. Items сделать как readonly. Если MenuItem имеет субменю, у него Items!=NULL.

Это мне тут же напомнило паттерн — Композитор, кажется?
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: Вопрос по наследованию
От: yxiie Украина www.enkord.com
Дата: 18.10.04 08:39
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>Бррр, не люблю стандартный RTTI. Ограниченный(узнать TypeID? А я хочу его фабрику и список членов. ), тормозной(так как расчитан на все случаи жизни, типа виртуального наследования).


ну насчет тормозного это вопрос спорный, но думаю в реализации меню RTTI не будет bottleneck'ом.
... << RSDN@Home 1.1.3 stable >>
Re: Вопрос по наследованию
От: Андрей  
Дата: 18.10.04 09:47
Оценка:
Всем спасибо за советы, за основу взят вариант от Олега Гашева.

P.S.
MaximE:
Твой вариант не проходит, т.к. при добавлении элемента в массив он не может создать экземпляр класса(т.к. у нас указан MenuItemBase, а он абстрактный)
Re[2]: Вопрос по наследованию
От: Bell Россия  
Дата: 18.10.04 10:13
Оценка: +1
Здравствуйте, Андрей, Вы писали:

А>P.S.

А>MaximE:
А>Твой вариант не проходит, т.к. при добавлении элемента в массив он не может создать экземпляр класса(т.к. у нас указан MenuItemBase, а он абстрактный)

А нельзя ли поподробнее — кто именно не может создать экземпляр класса, и где эти экземпляры храняться?
Если ты в MenuItem хранишь экземпляры MenuItemBase, то ты теряешь всю информацию о наследниках из-за срезки.

ЗЫ
А вообще, нормальный ОО-дизайн не требует информации о конкретном типе объекта.
Любите книгу — источник знаний (с) М.Горький
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.