В программе есть подсистема GUI и подсистема контейнера объектов. Обязаности контейнера - загружать объекты из файла, размещать в оперативке и сохранять в файл. Обязанности гуи - отображать их на екране и дать пользователю возможность модифицировать их. Вопрос в том, как спроектировать классы этих самых объектов? Пока есть такие варианты: 1.Сделать классы файловых объектов наследуемые от некоторого графического класса: Код (Text): class object_from_file: public graphical_object { }; 2.Сделать графический класс частью нашего класса: Код (Text): class object_from_file { graphical_object* screen_object; }; 3.Прямо в классе записать переменные и функции, которые будут определять его отображение на екране: Код (Text): class object_from_file { int x; int y; unsigned int color; void draw(); ... }; 4.В гуи создать контейнер графических объектов, каждый из которых будет содержать указатель на один из объектов контейнера файловых объектов и будет отвечать за его отображение: Код (Text): class graphical_object { object_from_file* internal_object; }; То есть вопрос в том, как связать классы из двух разных подсистем? Причем файловые объекты, так же как и графические, будут иметь свою иерархию для того, чтобы любой файловый объект мог быть отображен с помощью любого граического объекта, независимо от его сути. Поделитесь своим опытом отображения обектов на екране) Или подскажите как это реализовано в других прогах
т.е. graphical_object содержит дополнительную информацию, необходимую для вывода на экран object_from_file? координаты, размер и т.п. а-ля object_from_file1 = loadFile(...); graphical_object1 = createGraphicalObject(object_from_file1, position, rotation_angle, color); Если так, то лучше 4 вариант
Все четыре варианта страдают безнадежным убожеством. Курим гугл на тему "model-view-controller" (MVC)
Я сделал примеры специально убогими чтобы было видно проблему как она есть) Четвертый вариант подобен MVC. Спасибо за ответы)
эка бредятина на net ей самое место ) zStorm на масме делаю так: Код (Text): ; ------ Эллипс ------ __ELLIPSE STRUCT onext dd 0 ; ссылка на следующий объект в списке osize dd sizeof __ELLIPSE ; размер структуры otype dd OBJ_ELLIPSE ; тип объекта hent_rect RECT <> ; охватывающий прямоугольник (X1, Y1, X2, Y2) base_rect RECT <> ; прямоугольник задающий размер (X, Y, Width, Height) pen_obj dd 0 ; ссылка на объект пера fill_obj dd 0 ; ссылка на объект заливки base_angle REAL4 0.0 ; угол поворота start_angle REAL4 0.0 ; угол начала сектора end_angle REAL4 0.0 ; угол конца сектора lpGroup dd 0 ; ссылка (относительно списка) на объект - группа ... __ELLIPSE ENDS ; ------ Прямоугольник ------ __RECT STRUCT onext dd 0 ; ссылка на следующий объект в списке osize dd sizeof __RECT ; размер структуры otype dd OBJ_ELLISE ; тип объекта hent_rect RECT <> ; охватывающий прямоугольник (X1, Y1, X2, Y2) base_rect RECT <> ; прямоугольник задающий размер (X, Y, Width, Height) pen_obj dd 0 ; ссылка на объект пера fill_obj dd 0 ; ссылка на объект заливки base_angle REAL4 0.0 ; угол поворота lpGroup dd 0 ; ссылка (относительно списка) на объект - группа ... __RECT ENDS ; и т.д. ;======================================================================================================= ; Создание прямоугольника в списке SVP_Create_Rectangle MACRO X1, Y1, X2, Y2 ... ;======================================================================================================= ; Создание эллипса в списке (упорядочивание координат только для совместимости с прямоугольником) SVP_Create_Ellipse MACRO X1, Y1, X2, Y2 ... ; и т.п. ;============================================================================================== ; Макрос для векторной отрисовки списка объектов (через связанный список) draw_ObjectList MACRO ... "размер структуры" позволяет отбрасывать неиспользуемые поля в конце, "охватывающий прямоугольник" для быстрой проверки наличия обьекта в области экрана.
Какой кОшмар! Это же полное наличие отсутствия понимания базовых принципов ООП! К тому ж ветка называется "LANG.C"
Ursus Ты для начала правила форума что-ли почитал бы кстати под твоим сообщением есть ссылочка "Редактировать" и ты прямо сейчас можешь удалить неуместное гиперцицирование. ООП на асме возможен, но не всегда уместен ТС спрашивал как в других программах - я ему подбросил вариант. На С, ООП и т.п. сам переведёт если захочет, я, например, редко беру чужие примеры целиком, обычно подглядваю в них интересные идеи и адаптирую к своему ходу мысли
Член форума учел все правила задания темы, изложил грамотно вопрос и исходные данные, а вы в гугл. Не корректно!
Не знаю. Я бы сделал базовый и прозводные. Базовый с ссылочкой нехт и LoadNext по считанному типу и неким общим параметрам создающему производный, который сам считает персональные параметры (скажем, hfile - в конструктор) и приаттачит к нехт. Кроме того виртуальные Store и РrocessМессаж и что там еще надо. Можно еще предусмотреть ветвление и структурку для проверки правильности. Но, в принципе и потоково должно получиться, правда надо будет иметь и стоповые объекты. Конкретней сказать трудно, тк не понял конкретики проблемы. Впрочем это и на Цэ просто делается и просто выглядит.
сделай иерархию объектов и научи каждый из них отображать себя, реализовав в каждом из них pure virtual метод базового класса Base: Код (Text): class Base{ protected: Base(){} public: virtual ~Base(){} virtual void paint() = 0; //... }; class Derived1 : public Base{ public: //... virtual void paint(){ //конкретая реализация } }; class Derived2 : public Base{ public: //... virtual void paint(){ //конкретая реализация } }; //...
верно: есть базовый класс умеющий рисоваться (или же определяющий поведение), и есть его специализации (object_from_file одна из них), которые РАСШИРЯЮТ этот базовый класс. и все они знают как себя рисовать, т/к/ все реализуют pure virtual void pain() = 0; из базового. (см мой пост выше) тогда уж ввести какую-то внешнюю систему по отрисовке GUI и ей уже оперировать всеми переданными ей "файлами разных классов". но хранить указатель в кажд классе на систему его отрисовывающую - имхо изврат. (это может иметь смысл лишь в экзотическом случае, когда нужно реализовать возможность отрисовки разных объектов РАЗНЫМИ графич системами, но это уже отклонение от темы) они ничего не должны о ней знать, т/к графич система оперирует объектами (отрисовывая их), а не напротив. IMHO это фактически и есть мой вариант (описанный в посте выше)
Ну-ка тихо всем, а то в ад отправлю! Дело в том, что я примерно такую же задачу решаю. Вы уж простите, что на QT, но по-другому у меня нету. Смысл вот в чем: использовать фабрику. И так: К примеру, мы имеем некоторый GraphObject. Пусть у него имеется ряд свойств и методов, к которым мы вернемся чуть позже. Всякие сущности, должны быть созданы Создателем, ибо нет в мире механизма материализации из NULL. .h - описание class GraphObjectCreationFactory : public QObject { Q_OBJECT public: GraphObjectCreationFactory (QObject *parent = 0, const char *name = 0); private: GraphObject * _object_; GraphObject * TempObject; // нужен для копирования // Опишем состояния нашей фабрики signals: void object_tried_assume(); // попросили создать void object_created(); //Объект уже создан void object_ready_create();// Готов к создангию void object_deleted(); void object_updated(); //Класс! Теперь слоты public slots: void assume_object (GraphObject &); void delete_object (); void accept_obj(); ... бла бла бла... } Теперь - реализация. Я покажу на примере одной функции. Смысл - назначить объекту координаты и создать. Пусть у объекта есть X, Y, или чето еще Тогда .cpp - реализация GraphObjectCreationFactory::GraphObjectCreationFactory QObject *parent, const char *name) : QObject(parent, name) { connect ( this, SIGNAL ( object_tried_assume() ), SLOT ( assume_object(GraphObject &) ); } GraphObjectCreationFactory::assume_object (GraphObject &obj) { this->_object_=obj; Дальше уже процедуры рисования. emit object_created(); } Вот я так думаю сделать. Фабрика, Слушатель состояний, коллектор. Три сущности которые я намерен применить
Спасибо всем за ответы, попробую теперь изложить свои мысли varnie Делать класс внутренней логики программы производным от графического... ну не знаю. Его цель - сохранять данные. Как отображать его и данные внутри него - проблема GUI-подсистемы. Он, возможно, даже и не будет знать что его отображают на екране. Ему это незачем). Потому наследование будет не расширением функционала, а, скорее, добавлением избыточного функционала для него. А классы подсисетмы GUI не должны знать какую сущность им придеться отображать. Они просто должны уметь нарисовать линию или прямоугольник там, где им сказали не заботясь о сути. Отсюда напрашивается вывод - сделать третий клас, который совмещать в себе графический класс и класс из недр программы. Он же будет принимать сообщения. Он должен быть максимально простым. По сути выходит тот же model-view-controller... Всем спасибо за ответы, это проектное решение мне очень нравится) Код (Text): class mvc { program_logic_class* some_internal_object; gui_class* some_gui_object; public: void UserAction1(); void UserAction2(); void UserAction3(); }; Вижу следующие недостатки: 1.Возростает сложность программы (хотя не факт, может даже упроститься) 2.Забота об указателях - ведь два объекта, которые на указателях - они из разных "миров" Я вот сейчас прочитал свой пост, затем несколько раз прочитал весь тред и понял что все мои рассуждения на эту тему абсолютно бессмысленны пока я не спроектирую более детально подсистему GUI и внутреннюю логику. Может, в mvc нет никакой нужды и обойтись простым наследованием... Буду отписываться здесь по ходу дела)
zStorm в любом случае тогда тебе придется научить эту GUI подсистему оперировать со всеми твоими различными производными классами (CFileObject etc). как ты планируешь это сделать? упаси Страуструп тебя юзать Код (Text): if (dynamic_cast<MyDerivedClass1*>(pObject) != NULL ){ action1(); ) else if (dynamic_cast<MyDerivedClass2*>(pObject) != NULL ){ action2(); ) ... это я к тому что нужно хорошо подумать как это реализовать, если классический подход через полиморфизм ты отбрасываешь... или же можно ввести какую-то свою внутреннюю прозрачную систему классификации и по ней уже будет ясно когО и кАк отрисовывать. к примеру, отображаемые объекты разных подклассов хранить в разных контейнерах. но эта идея мне не нравится. osrootd +1 а также советую Дж. Коплиен. "Мультипарадигменное проектирование для C++"