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

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

ru
Offline Offline

« : 16-08-2009 10:41 » 

абстрактное наследование

учебная зачачка, тренируюсь с наследованием:

допустим есть библиотека, создающая на экране одно\несколько окон с задаными размерами и координатами и позволяющая на нем рисовать точки и линии и сохраняющая текущие координаты после рисования

допустим хочу создать абстрактный класс shape, который будет являться интерфейсом для рисования фигур типа точек, линий, прямоугольников, треугольников связанных друг с другом центральными или краевыми точками, чтобы понять приемущество использования наследования абстрактного класса, по сравнению с наследованием от базового класса или включением объектов вместо наследования в потомок

как лучше спроектировать интерфейс shape?

на каких задачках будут очевидны вышеописаные приемущества?

так ладно такая задачка:
считать с ifstream последовательности символов:
{link shape_num shape_point | pos x y } shape_name [ shape specific ]
и отобразить вышеописаные формы на экране ( под формами понимается скорее всего простая полигональная фигура )

как ее решать без наследования и виртуальных функций я не представляю

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

« Последнее редактирование: 16-08-2009 12:14 от Mayor » Записан

1n c0de we trust
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 16-08-2009 12:17 » new

Абстрактный класс описывает интерфейс всех наследуемых классов. От него нельзя получить экземпляр класса. Также абстрактный класс заставляет программистов при разработке своих классов на основе абстрактного, полностью переопределить все абстрактные методы  в своем классе. Это будет очень хорошо сказываться при разработке в больших коллективах. Когда аналитик разрабатывает дизайн проетка на основе интерфейсов. А программисты уже наполняют мясом скелет.
Все выводы о примушествах делай сам.
« Последнее редактирование: 16-08-2009 12:20 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Mayor
Специалист

ru
Offline Offline

« Ответ #2 : 17-08-2009 01:28 » 

Это будет очень хорошо сказываться при разработке в больших коллективах. Когда аналитик разрабатывает дизайн проетка на основе интерфейсов. А программисты уже наполняют мясом скелет.
Все выводы о примушествах делай сам.

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

1n c0de we trust
Mayor
Специалист

ru
Offline Offline

« Ответ #3 : 21-08-2009 14:34 » 

так, допустим уже спроектирован и реализован интерфейс окна, в который будут выводится полигональные формы:
Код:
class window {
public:
virtual point current() =0 ;
virtual void current(const point& p) = 0;
virtual void line(const point& p) =0;
virtual void paint()=0;
virtual ~window() {
cout<<"destroing abstract window"<<endl;
};
};

если описать интерфейс форм как:
Код:
class shape {
public:
virtual point getEdge(int direction)=0; // выдает координаты края\центра фигуры
virtual bool setPoint(const point& p)=0; /* добавляет координату для построения фигуры,
 возвращая false когда получена последняя координата необходимая для построения */
virtual void draw(window* w) =0; // рисует фигуру в окне
}

то какие заморочки могут возникнуть в плане реализации?
Записан

1n c0de we trust
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #4 : 21-08-2009 15:43 » 

Mayor, ты опять всё наизнанку выворачиваешь: сначала пусть твой интерфейс будет просто пустой, помимо очевидных методов. Потом будешь по мере необходимости пополнять. Это будет не трудно, если иерархия классов продумана. Не интерфейс, а именно иерархия. Которую, впрочем, всегда можно будет поменять, если что то совсем ясно не так ) Признак того, что что то не так - когда появляется "замученность" при очередном решении
Записан

Mayor
Специалист

ru
Offline Offline

« Ответ #5 : 22-08-2009 03:18 » 

Mayor, ты опять всё наизнанку выворачиваешь: сначала пусть твой интерфейс будет просто пустой, помимо очевидных методов. Потом будешь по мере необходимости пополнять. Это будет не трудно, если иерархия классов продумана. Не интерфейс, а именно иерархия. Которую, впрочем, всегда можно будет поменять, если что то совсем ясно не так ) Признак того, что что то не так - когда появляется "замученность" при очередном решении

куда тут упрощать?
зачем тут иерархия классов?

если потом добавлять к интерфейсу, то мне придется переписывать каждый наследующий его класс и не факт, что после этого будет работать стороний код, обращающийся к интерфейсу
Записан

1n c0de we trust
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #6 : 22-08-2009 07:22 » 

1) если ты что то добавляешь - то тебе ПО ЛЮБОМУ придётся переписывать потомков, так как именно потому ты и добавляешь ))
2) если старые методы не трогать, то на старую совместимость новые методы не повлияют.
Записан

Mayor
Специалист

ru
Offline Offline

« Ответ #7 : 22-08-2009 07:36 » 

1) если ты что то добавляешь - то тебе ПО ЛЮБОМУ придётся переписывать потомков, так как именно потому ты и добавляешь ))
2) если старые методы не трогать, то на старую совместимость новые методы не повлияют.

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

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

помоему ты сам наизнанку понятие интефейса выворачиваешь
Записан

1n c0de we trust
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #8 : 22-08-2009 08:29 » 

я не знаю, что ты под интерфейсом понимаешь, я тебе из личного опыта написания программ говорю. Можно старый метод ТАК переправить, что всё старое не будет работать (я именно про корректную работу, а не про радость компилирования)
Записан

Mayor
Специалист

ru
Offline Offline

« Ответ #9 : 22-08-2009 15:45 » 

в общем написал код ...
подавая на std::cin последовательность команд типа:
Код:
png_window
quad 10 20
30 40
60 70
30 23
quad 15 40
60 40
60 120
15 120
rect 80 80
110 120

получил картинку:

до меня еще до сих пор не доходит полная мощь сочетания наследования с виртуальными функциями, раньше верхом крутости казалось: рантайм компилятор формул, построенный на конечных автоматах через манипуляции с указателями на функции ...
а щас все тоже самое ... только после того как только что скомпиленая хрень стала выводить эти крякозяблы на экран через хлиб, решил я добавить возможность вывода их вместо экрана в png файл - если бы раньше пришлось переписывать все приложение с 0 или потратив в 2 раза больше времени ограничится переделкой под это половины кода ... то сейчас просто добавил в проект 1 объектный файл, добавив пару строчек в factory.cpp, безо всякой перекомпиляции остальных файлов проекта - новый код по команде в текстовом файле: png_window ( вместо xlib_window ) перенаправил весь вывод с экрана в png файл ...
тоже самое с новой формой rect - ее исходиники + пара строчек в factory и также без перекомпиляции остального проекта - готова обработка нового типа данных

алексей, привел меня к мысли заценить иерархию классов ...
допустим такая задачка:
имеется уже работающий код:
Код:
#include "factory.h"
#include <iostream>
using std::cin;
using std::istream;
shape* get_shape_type(istream& f){
string s;
int err=0;
shape* ps=0;
while(f>>s) {
ps=shape_factory(s);
if (ps ) break;
err++;
}
return ps;
}
void fill_shape(shape* ps,istream& f){
point p;
f>>p.x>>p.y;
while( ps->setPoint(p) ) f>>p.x>>p.y;
}

using std::cerr;
using std::endl;
#include <vector>
using std::vector;
int main() {
string s="xlib_window";
cin>>s;
window* p=window_factory(s,400,500,"alpha");
if (!p) cerr<<"wrong window type: "<<s<<endl,exit(1);
typedef vector<shape*> vps;
vps v;
while(1) {
shape* ps=get_shape_type(cin);
if (!ps) break;
v.push_back(ps);
fill_shape(ps,cin);
}
for ( size_t i=0; i<v.size() ; i++ ) v[i]->draw(p);
p->paint();
delete p;
for ( size_t i=0; i<v.size() ; i++ ) delete v[i];
        return 0;
}
c минимальными изменениями в нем и без перекомпиляции\модификации классов унаследованых от window, shape и уже реализованных, сохранением возможности обрабатывать предыдущие текстовые данные ...

добавить возможность создания форм ( в тч унаследованных от уже реализованных ) со способностью задавать толщину линии и ее прерывистость

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


* alpha.png (2.01 Кб - загружено 1076 раз.)
« Последнее редактирование: 22-08-2009 16:23 от Mayor » Записан

1n c0de we trust
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #10 : 23-08-2009 05:31 » 

Mayor, непонятна задача. Исходники, я так понимаю, имеются. Что за резервы ? Что за формы ?

попытаюсь отгадать

например, так (HDC - хендл контекста устройства)

Код:
//старый метод
void fill_shape(shape* ps,istream& f){
point p;
f>>p.x>>p.y;
while( ps->setPoint(p) ) f>>p.x>>p.y;
}

//новый метод
void fill_shape(shape* ps,istream& f,HDC hdc=0){
if(!hdc)
{
//старый метод
point p;
f>>p.x>>p.y;
while( ps->setPoint(p) ) f>>p.x>>p.y;
}
else
{
//рисуем на контексте  hdc
}
}
Записан

Mayor
Специалист

ru
Offline Offline

« Ответ #11 : 23-08-2009 06:05 » 

Mayor, непонятна задача. Исходники, я так понимаю, имеются. Что за резервы ? Что за формы ?

попытаюсь отгадать

например, так (HDC - хендл контекста устройства)

Код:
//старый метод
void fill_shape(shape* ps,istream& f){
point p;
f>>p.x>>p.y;
while( ps->setPoint(p) ) f>>p.x>>p.y;
}

//новый метод
void fill_shape(shape* ps,istream& f,HDC hdc=0){
if(!hdc)
{
//старый метод
point p;
f>>p.x>>p.y;
while( ps->setPoint(p) ) f>>p.x>>p.y;
}
else
{
//рисуем на контексте  hdc
}
}

неа не то, fill_shape просто закачивает однородными данными геометрии потомка shape, пока он не скажет, что данных ему достаточно

вот где происходит непосредственно рисование ( уже после того как все потомки закачаны их геометрией )
for ( size_t i=0; i<v.size() ; i++ ) v->draw(p);
и контекст ( в данном случае указатель на объект окна ) передается форме непосредственно перед рисованием, те можно нарисовать данную форму сразу на нескольких "устройствах"

* 2cairo.tar.bz2 (143.83 Кб - загружено 952 раз.)
« Последнее редактирование: 23-08-2009 06:13 от Mayor » Записан

1n c0de we trust
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines