Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 08.05.2013, 16:27   #11
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от rrrFer Посмотреть сообщение
Если не брать во внимание веские аргументы Саттера (аля "глупая книжная истина"), то я не думаю что порождение многоугольника, состоящего из точек, от точки что-то может улучшить в этом случае.

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

Например:

Код:
struct Agent: protected Servise<Agent> { ... };
Agent не является частным случаем Servise<Agent>
Однако же он от него унаследован.

Ему нужен был функционал сервисов.

Это довольно распространенный способ подключать к классу различные службы:

struct Agent: boost::noncopyable //запрет на копирование
{ ... };

struct Agent: protected EventSystem //подключение к системе сообщений
{ ... };

struct Agent: IFace1,IFace2 //интерфейсные контракты
{ ... };

struct Agent: Mechanism //модификация механизма
{ ... };

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

Всякие там паттерны "цепочка", когда на шаблонах генерируется линейка наследования по различным криетриям, и тп вещи.


Теперь представь себе: у тебя есть куча классов по проекту: всякие картинки, кнопки, анимации и тп.

Все они обязаны иметь дизайн вида:

Картинка.УстановитьХУ(арг);
Кнопка.УстановитьХУ(арг);
Анимация.УстановитьХУ(арг);

И везде за это отвечает одна и та же механика.
Лично я сделаю один единственный класс-сеттер/геттер, и его реализацию унаследую для каждого нужного мне агента.

А что сделаешь ты?

Будешь копипастить реализацию каждый раз заново?

Последний раз редактировалось _Bers; 08.05.2013 в 16:35.
_Bers вне форума Ответить с цитированием
Старый 08.05.2013, 16:34   #12
alexSo
 
Регистрация: 06.05.2013
Сообщений: 7
По умолчанию

Цитата:
Сообщение от rrrFer Посмотреть сообщение
Если не брать во внимание веские аргументы Саттера (аля "глупая книжная истина"), то я не думаю что порождение многоугольника, состоящего из точек, от точки что-то может улучшить в этом случае.

И если ты в своей конторе пишешь такой код, подумай чуть о новобранцах, которые придут работать и будут долго пытаца понять чем же многоугольник так провинился.

в какой строчке, какая ошибка?
Да спс уже не надо я код переписал. из за string наверное ошибка была
alexSo вне форума Ответить с цитированием
Старый 08.05.2013, 18:22   #13
rrrFer
Санитар
Старожил
 
Аватар для rrrFer
 
Регистрация: 04.10.2008
Сообщений: 2,618
По умолчанию

Цитата:
Это довольно распространенный способ подключать к классу различные службы:
и все примеры с темой слабо связаны.
Цитата:
boost::noncopyable
Если ты отнаследовался от него, то да, твой класс будет частным случаем некопируемого класса ) в терминологии Саттера отражать зависимость "является", т.е. твой класс "является некопируемым".

Цитата:
При наследовании, наследник наследует функционал от своего базового класса. Сейчас я уже точно не помню, была ли эта прописная истина описана в книге Саттера.
истина прописная, но если вернуца к примеру темы, то ты щитаешь, что если многоугольнику нужен функционал точки, то его сразу же надо от точки порождать? Я щитаю, что наследовать (по крайней мере, открыто) надо если потомок может быть использован в любом месте вместо базового класса (куцо сформулировано, но, вроде бы, это тоже прописная истина), т.е. полиморфно.

Цитата:
Теперь представь себе: у тебя есть куча классов по проекту: всякие картинки, кнопки, анимации и тп.

Все они обязаны иметь дизайн вида:

Картинка.УстановитьХУ(арг);
Кнопка.УстановитьХУ(арг);
Анимация.УстановитьХУ(арг);

Лично я сделаю один единственный класс-сеттер/геттер, и его реализацию унаследую для каждого нужного мне агента.

А что сделаешь ты?
Примерно тоже самое, только назову базовый класс примерно "Графический объект" или "объект плоскости"/"объект экрана" (судя по УстановитьХУ они будут схожи тока в том, что их можно двигать по плоскости). И скажу, что и кнопка, и картинка и график и окошко - объекты плоскости, т.е. частные случаи, или в терминологии Саттера "картинка является объектом плоскости".

Но, вцелом, мне кажеца я понял что ты имел ввиду, что редко объекты моделируют какие-то предметы, которые легко представить (тот же boost::noncopyable из твоих примеров), и поэтому все эти книжные штуки притягиваюца за уши. Если мысль угадал верно, то согласен
rrrFer вне форума Ответить с цитированием
Старый 08.05.2013, 19:40   #14
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от rrrFer Посмотреть сообщение
истина прописная, но если вернуца к примеру темы, то ты щитаешь, что если многоугольнику нужен функционал точки, то его сразу же надо от точки порождать? Я щитаю, что наследовать (по крайней мере, открыто) надо если потомок может быть использован в любом месте вместо базового класса (куцо сформулировано, но, вроде бы, это тоже прописная истина), т.е. полиморфно.
...

Но, вцелом, мне кажеца я понял что ты имел ввиду, что редко объекты моделируют какие-то предметы, которые легко представить (тот же boost::noncopyable из твоих примеров), и поэтому все эти книжные штуки притягиваюца за уши. Если мысль угадал верно, то согласен
Моя мысль была в том, что главная задача наследования - это получение конечных классов с нужным функционалом, который собирается как из деталей на базе предков.

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

Зачастую базовые классы являются лишь источником функционала, либо носят служебно-вспомогательный характер (например, boost::noncopyable или EventSystem)

То есть, в принципе не предполагаются функции типа:
Код:
void Foo(const EventSystem& src);
Что до полиморфных семейств (там, где реально действует правило Саттера) - там по другому и не сделаешь. Язык так устроен.
...


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

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

Код:
Многоугольник: protected Точка
{
   ...
};
Что бы не копипастить для многоугольника методы аля SetXY

Если мне не изменяет память: именно Саттер в своей книге писал, что не до конца понимает смысла защищенного наследования.

Это потому, что данный вид наследования нарушает его концепцию о наследовании.

Такой вид наследования явно подчеркивает идею программиста: многоугольник унаследовал весь функционал точки, его данные и его методы, но при этом точкой он не является.

Таким образом, вы в принципе не сможете использовать многоугольник в функциях, которые принимают точку:

void Foo(const Point& point) { .... }
...

CTetragon tetragon;
Foo(tetragon); //error: 'Point' is an inaccessible base of 'CTetragon'
Ошибка будет времени компиляции.

Можно конечно унаследоваться от boost::noncopyable, и назвать потомка частным случаем некопируемого класса. Но это не более, чем буквоедство.

На практике не важно, как это называется, а важно, как это работает.
Унаследоваться можно всегда, если это удобнее, быстрее, и экономит время на отладке.


Примерно тоже самое, только назову базовый класс примерно "Графический объект" или "объект плоскости"/"объект экрана" (судя по УстановитьХУ они будут схожи тока в том, что их можно двигать по плоскости). И скажу, что и кнопка, и картинка и график и окошко - объекты плоскости, т.е. частные случаи, или в терминологии Саттера "картинка является объектом плоскости".

Вопрос не в том, как это можно назвать, а в том, как это можно реализовать.

Если у них у всех реализация метода SetXY идентичная, и она идентична методам примитива Point, то нет ни одной причины в каждом новом классе заново её копипастить. В том числе, нет ни одной причины, копипастить реализацию в интерфейс:

Код:
struct Point
{
   void SetXY(param){ ...}
};

struct IGraphicObj: protected Point
{ 
  ~virtual IGraphicObj(){...}
   virtual void Show()=0;
};

Image:  IGraphicObj{...};
Button: IGraphicObj{...};
....
Если у нас уже есть проверенный протестированный класс Точки, то мы всегда можем использовать его функционал. А не копипастить код, который опять заново нужно будет проверять и тестировать.

Последний раз редактировалось _Bers; 08.05.2013 в 19:56.
_Bers вне форума Ответить с цитированием
Старый 08.05.2013, 20:22   #15
rrrFer
Санитар
Старожил
 
Аватар для rrrFer
 
Регистрация: 04.10.2008
Сообщений: 2,618
По умолчанию

Цитата:
Вопрос не в том, как это можно назвать, а в том, как это можно реализовать.
реализовать примерно также, тока без Point
Цитата:
Если у них у всех реализация метода SetXY идентичная, и она идентична методам примитива Point, то нет ни одной причины в каждом новом классе заново её копипастить. В том числе, нет ни одной причины, копипастить реализацию в интерфейс:
Почему бы не выкинуть Point в этом простом примере и не засунуть реализацию в графический объект? (засунуть 1 раз, не копипастить ничего). Точку выкинем, "не плоди сущности без необходимости" (так Оккама завещал)

----

добавил: а если приспичит выводить на экран точку, то можно будет вспомнить, что она и есть графический объек, дописать
class Point: public GraphicObj{...};

Но МБ не прав, подскажи в чем?
rrrFer вне форума Ответить с цитированием
Старый 08.05.2013, 21:08   #16
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от rrrFer Посмотреть сообщение
реализовать примерно также, тока без Point
Почему бы не выкинуть Point в этом простом примере и не засунуть реализацию в графический объект? (засунуть 1 раз, не копипастить ничего). Точку выкинем, "не плоди сущности без необходимости" (так Оккама завещал)
Мы не создаем Точку только для того, что бы от неё унаследоваться. Потому что Оккама не велит

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

На самом деле, нельзя засунуть готовую реализацию чевотов не скопипастив её (ну или не набрав её заново).

Можно конечно выбросить точку из иерархии наследования, и скопипастить её код в интерфейс. И для простых ситуаций это даже предпочтительнее, потому что весь функционал перед глазами, а не размазан по кучке мелких классов. Так удобнее потом будет читать код.

Но если это целая служба, имеющая кучу всяких заморочек,
Если даже простейшее SetXY на самом деле выполняет кучу всякой всячины (проверка логических координат с учетом реальных размеров окна и виртуального масштаба и бла бла бла) и все уже отлажено и протестировано, то копипаста здесь не добавит никаких удобств, а только сожрет время на новую отладку и тесты.

Цитата:
Сообщение от rrrFer Посмотреть сообщение
добавил: а если приспичит выводить на экран точку, то можно будет вспомнить, что она и есть графический объект, дописать
class Point: public GraphicObj{...};

Но МБ не прав, подскажи в чем?
Ну смотря как приспичит. Точки из которых состоит многоугольник не являются графическими элементами. Они являются координатными элементами.
Такую точку правильнее было бы назвать "логическим объектом", а не "графическим".
Код:
struct Point{  float X,Y };
----------------------------------

А вот графическая точка - грубо говоря, это просто цвет пикселя.
Например: точку можно нарисовать поверх картинки. Просто перекрасить один из её пикселей.

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

Тоже самое касается линий: это просто прозрачная картинка, на которую нанесена линия.

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

О то Оккама заругает
_Bers вне форума Ответить с цитированием
Старый 09.05.2013, 03:44   #17
rrrFer
Санитар
Старожил
 
Аватар для rrrFer
 
Регистрация: 04.10.2008
Сообщений: 2,618
По умолчанию

Цитата:
Мы не создаем Точку только для того, что бы от неё унаследоваться. Потому что Оккама не велит.
...
Так удобнее потом будет читать код.
ну вот, ты мне все прояснил
Цитата:
О то Оккама заругает
он никогда не ругает, сразу режет
rrrFer вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Метод перебора, Метод дихотомии, Метод золотого сечения Delphi !!! OneBri Помощь студентам 0 03.10.2012 08:42
Конструктор,метод вывода на экран Display, метод для преобразования в строку toString в Delphi Чумак Татьяна Помощь студентам 6 03.04.2012 11:58
исследовать метод квадратных корней и метод Холецкого для решения СЛАУ Vит@x@ Помощь студентам 0 22.11.2011 10:47
Задача Коммивояжера. Метод Монте-Карло и метод приращений. [Паскаль] U9110 Помощь студентам 4 06.04.2011 09:48
Turbo Pascal[програмыки : текстовая\метод симпсона\метод половинного деления qsccsq Помощь студентам 7 24.12.2010 05:23