Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: про ооп  (Прочитано 8911 раз)
0 Пользователей и 1 Гость смотрят эту тему.
titov_alex
Участник

ru
Offline Offline

« : 17-02-2004 11:57 » 

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

вот какую штуковину я придумал:

class CPoint : list <CPoint> {
...

list - мой шаблонный класс, сильно упрощенный аналог STL-ного - безо всяких иттераторов и т.п. - просто динамический двусвязный (вроде - уже не помню) список с перегруженным оператором []

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

tree[index1][index2][index3].<поле или метод>  8)  

конечно, в классе TPoint пришлось заново перегружать оператор [] - т.к. он из list берется вместе с остальными мемберами как приват (чтобы другие методы класса list не были доступны из-вне класса CPoint).

вроде как это довольно удобно, причем все уже вроде как реализовано... но возник "этический" вопрос - а насколько такого рода конструкция соответствует идеалогии ООП, ведь класс получается дочерним фиг знает чему :?
Вот, спасибо за ответы/советы Улыбаюсь
Записан
Asan
Гость
« Ответ #1 : 19-02-2004 08:08 » 

Цитата: titov_alex
надо было написать некий класс, описывающий объект из списка, причем некоторые из этих объектов также могли быть списками...

Может, в твоем случае подойдет композиция. Что то типа:

Код:

class BaseElem {
//...
public:
    virtual void Operation1() = 0;
    virtual void Add(BaseElem*) = 0;
//...
};

class Simple: public BaseElem {
public:
//...
     void operation1() {  /*Делать нечто */}
};

class Composite: public BaseElem {
    list<BaseElem*> _list;
public:
//...
    void operatio1() {
        for (list<BaseElem*>::iterator it = _list.begin();
              it != _list.end();
              ++it) {
                  *it->operation1(); }
        }

};
« Последнее редактирование: 24-11-2007 13:24 от Алексей1153++ » Записан
titov_alex
Участник

ru
Offline Offline

« Ответ #2 : 19-02-2004 09:29 » 

to Asan:
Цитата: Asan
Может, в твоем случае подойдет композиция. Что то типа:
Если чесно, не совсем понял, что имелось ввиду  :oops:

А именно:
1) зачем нужен класс Simple - я не усмотрел, где он используется?
2) как в этом случае обращаться к произвольному элементу дерева?

в твоем примере, я так понял, для каждого объекта типа Composite заводится список объектов типа BaseElem.

Но т.о., мы получаем лишь двухуровневое дерево! А мне нужно "бесконечное" с произвольным (от 0 до бесконечности) количеством дочерних элементов для каждого узла (каждый элемент списка может сам оказаться списком техже самых элементов, причем условие - ВСЕ элементы дерева, включая корень являются объектами одного типа)

to All:
И еще - все-таки интересно что вы скажите  про конструкцию в моем первом посте

Код:
class CPoint : list <CPoint> {
...
как ее можно назвать/пояснить/обосновать - или эта конструкция - нонсенс с точки зрения ООП??? :?
« Последнее редактирование: 24-11-2007 13:13 от Алексей1153++ » Записан
Asan
Гость
« Ответ #3 : 19-02-2004 11:24 » 

Ты бы написал подробней, что тебе надо и для чего.
Насколько я понял, тебе нужно нужно хранить в списке некие элементы, причем элемент может быть либо собственно "элементом",
либо контейнером "элементов", каждый из которых так же может быть списком элементов, каждый из которых...........
Или у тебя каждый элемент списка содержит еще и список других элементов?
Я же не знаю твою задачу, поэтому и предложил композицию для начала.

Цитата: titov_alex
to Asan:
А именно:
1) зачем нужен класс Simple - я не усмотрел, где он используется?

Если коротко, "композиция" подразумевает что:
Есть базовый класс, который определяет общий интерфейс.
Есть "листовые" классы-наследники, представляющие собст-но "элементы", есть классы-контейнеры, содержащие списки указателей базового класса.
Т. о., имея указатель на базовый класс, клиент работает через единый интерфейс как с простыми, так и составными объектами.

Цитата
2) как в этом случае обращаться к произвольному элементу дерева?

Хм, а как в твоем случае обращатся к произвольному элементу дерева?  
tree[1][2][3] или tree[1][2][3][4][5]?


Цитата
в твоем примере, я так понял, для каждого объекта типа Composite заводится список объектов типа BaseElem.

Но т.о., мы получаем лишь двухуровневое дерево! А мне нужно "бесконечное" с произвольным (от 0 до бесконечности) количеством дочерних элементов для каждого узла (каждый элемент списка может сам оказаться списком техже самых элементов, причем условие - ВСЕ элементы дерева, включая корень являются объектами одного типа)

Как раз таки дерево получается абсолютно любого уровня, т.к. Composite содержит указатели на базовый класс, а объекты, на которые они указывают,  могут быть как листовыми, так и теми же Composite-ами.

Цитата
to All:
И еще - все-таки интересно что вы скажите  про конструкцию в моем первом посте

Код:
class CPoint : list <CPoint> {
...
как ее можно назвать/пояснить/обосновать - или эта конструкция - нонсенс с точки зрения ООП??? :?

Да вроде нонсенса тут никакого  нет.
« Последнее редактирование: 24-11-2007 13:14 от Алексей1153++ » Записан
titov_alex
Участник

ru
Offline Offline

« Ответ #4 : 19-02-2004 11:55 » 

Цитата: Asan
Ты бы написал подробней, что тебе надо и для чего.
Насколько я понял, тебе нужно нужно хранить в списке некие элементы, причем элемент может быть либо собственно "элементом",
либо контейнером "элементов", каждый из которых так же может быть списком элементов, каждый из которых...........
Или у тебя каждый элемент списка содержит еще и список других элементов?
Я же не знаю твою задачу, поэтому и предложил композицию для начала.
Изначально - такая штука понадобилась для реализации своей обертки для меню программы. Кстати, я ее уже полностью реализовал, использую именно ту конструкцию - вроде все работает

Цитата: Asan
Если коротко, "композиция" подразумевает что:
Есть базовый класс, который определяет общий интерфейс.
Есть "листовые" классы-наследники, представляющие собст-но "элементы", есть классы-контейнеры, содержащие списки указателей базового класса.
Т. о., имея указатель на базовый класс, клиент работает через единый интерфейс как с простыми, так и составными объектами.
Все, понял. Просто недавно программирую с использованием классов, поэтому и не знаю всех способов его применения - довольно красивый спосоп, надо сказать Улыбаюсь

Цитата: Asan
Хм, а как в твоем случае обращатся к произвольному элементу дерева?  
tree[1][2][3] или tree[1][2][3][4][5]?
Именно - ради этого я и заводил такой вот класс... чтобы к менюхе был удобный доступ (он чем-то похож на доступ к менюхе из VBA под Access97, под которым я в свое время плотно работал - там мне нравилось, вот и тут захотел Улыбаюсь )

Вот пример, как используется класс (кусок, где идет работа с менюхой):
Код:
 
  CMenu Menu;
  Menu.InitMenu(m_hWnd); // Инициализация класса менюхи и ее самой
  Menu.CreateMenu("&File",0,MF_STRING,NULL); // Создаем подменю
  // Дальше идет добавление пунктов меню
  Menu[0].AddMenu(IDCMD_START_NEW_SEANS,    "New",   0, MF_STRING,NULL);
  Menu[0].AddMenu(IDCMD_STOP_CURRENT_SEAND, "Close", 1, MF_STRING,NULL);
  Menu[0].AddMenu(IDCMD_CLOSE_APP,          "Exit",  2, MF_STRING,NULL);
  return 0;
Как видишь, обращение абсолютно одинаковое как к переменной Menu, так и к конструкции Menu[0] - они оказываются одного типа Улыбаюсь
Т.о., в общем случае я могу обращаться хоть Menu[1]..<n раз>...[n], хоть указывая любые другие индексы и получу объект типа CMenu, с которым могу делать все то же самое, что и с корнем

Цитата: Asan
Как раз таки дерево получается абсолютно любого уровня, т.к. Composite содержит указатели на базовый класс, а объекты, на которые они указывают,  могут быть как листовыми, так и теми же Composite-ами.
угу, я понял.. но все-таки, щас обращение не такое удобное получается к объектам

Цитата: Asan
Да вроде нонсенса тут никакого  нет.
меня тут, сообственно, смущает только то, что базовый класс специализируется через дочерний (или наоборот - дочерний класс определяется через шаблон, специализированный через потомка..  :? ). Довольно трудно себе представить такую картину, при том, что принцип ООП позволяет создавать "прозрачные" программы.
« Последнее редактирование: 24-11-2007 13:14 от Алексей1153++ » Записан
Asan
Гость
« Ответ #5 : 19-02-2004 13:24 » 

Цитата: titov_alex
меня тут, сообственно, смущает только то, что базовый класс специализируется через дочерний (или наоборот - дочерний класс определяется через шаблон, специализированный через потомка..  :? ). Довольно трудно себе представить такую картину, при том, что принцип ООП позволяет создавать "прозрачные" программы.

Ну не нравится наследование, можно через агрегирование, например:
Код:
class CMenu {
    list<CMenu> _list;

public:
    CMenu& operator[] (int index) {
        return _list[index];
    }
};

Меня смущает, что пункт меню и подменю в принцепе-то объекты разные, пункт меню не может иметь вложенных пунктов, а подменю не имеет ассоциированного с ней идентификатора или команды, зато хранит другие пункты. Пункту меню не нужно иметь функциональность списка. А у тебя получается, что на любой объект CMenu меню можно навесить что угодно. Или ошибиться с индексами, и получить "неправильный" CMenu..
К тому же, если понадобится получить доступ к какому либо
конкретному CMenu, это ж надо еще и вспомнить его [n]..[n].

В общем, не знаю. Мои познания в ООП не настолько глубоки Жаль , как хотелось бы. Может, кто еще что нибудь умное скажет по этому поводу Улыбаюсь?
« Последнее редактирование: 24-11-2007 13:15 от Алексей1153++ » Записан
ysv_
Помогающий

ua
Offline Offline

« Ответ #6 : 22-02-2004 22:27 » 

Цитата

titov_alex писал(а):

меня тут, сообственно, смущает только то, что базовый класс специализируется через дочерний (или наоборот - дочерний класс определяется через шаблон, специализированный через потомка..  ). Довольно трудно себе представить такую картину, при том, что принцип ООП позволяет создавать "прозрачные" программы.


Кстати такой конструкцией class A: public class Singleton<A> пользуются для превращения класса в синглтон. (Описан в Андрей Александреску. "Современное проектирование"). Так что можеш быть спокоен Улыбаюсь. Его считают аналогом полиморфных классов для шаблонных классов. Насколько я помню в шаблонных классах существуют какие-то проблемы с использованием виртуальных функций.
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #7 : 26-02-2004 10:54 » 

Цитата
Насколько я помню в шаблонных классах существуют какие-то проблемы с использованием виртуальных функций.
Есть не которое неудобство ... поскольку реализация таких функций должна находиться в томже хеадере что и объявление класса

насчет
Цитата
Код:
class BaseElem {
//...
public:
    virtual void Operation1() = 0;
    virtual void Add(BaseElem*) = 0;
//...
};

class Simple: public BaseElem {
public:
//...
     void operation1() {  /*Делать нечто */}
};

class Composite: public BaseElem {
    list<BaseElem*> _list;
public:
//...
    void operatio1() {
        for (list<BaseElem*>::iterator it = _list.begin();
              it != _list.end();
              ++it) {
                  *it->operation1(); }
        }

};

это реализация паттерна COMPOSITE (Приемы объектно ориентированного проектирования, паттерны проектирования авторы ... так называемая "банда четырех")

to Asan а по поводу
Цитата
Хм, а как в твоем случае обращатся к произвольному элементу дерева?
tree[1][2][3] или tree[1][2][3][4][5]?

если надо это .... то пожалуйста, проблемы то нет

Код:
class BaseElem
{
public:
...
   virtual BaseElement * operator[] (int) { return 0; }
};

class Simple: public BaseElem {
{
public:
...
   BaseElement * operator[] (int);  // реализация на твой вкус например { return 0;}
};

class Composite: public BaseElem
{
    typedef std::list<BaseElem *> List;
    List   theList;
public:
...
    BaseElem * operatior[] (int index)
    {
        List::iterator iter = theList.begin();
        for (; iter != theList.end() ; ++iter)
              if (!index--)
                 return *iter;
        return 0;
    }
};

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

тогда в случае вектора мыбы имели это
Код:
class Composite: public BaseElem
{
    typedef std::vector<BaseElem *> Vector;
    Vector   theVector;
public:
...
    BaseElem * operatior[] (int index)
    {
        return theVector[index];
    }
};
что короче и главное существенно быстрее
« Последнее редактирование: 24-11-2007 13:20 от Алексей1153++ » Записан

С уважением Lapulya
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines