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

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: абстрактное наследование  (Прочитано 10506 раз)
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 » 

Абстрактный класс описывает интерфейс всех наследуемых классов. От него нельзя получить экземпляр класса. Также абстрактный класс заставляет программистов при разработке своих классов на основе абстрактного, полностью переопределить все абстрактные методы  в своем классе. Это будет очень хорошо сказываться при разработке в больших коллективах. Когда аналитик разрабатывает дизайн проетка на основе интерфейсов. А программисты уже наполняют мясом скелет.
Все выводы о примушествах делай сам.
« Последнее редактирование: 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 Кб - загружено 1000 раз.)
« Последнее редактирование: 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 Кб - загружено 867 раз.)
« Последнее редактирование: 23-08-2009 06:13 от Mayor » Записан

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

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines