Перейти к содержимому


Фото

Классификация класса


  • Чтобы отвечать, сперва войдите на форум
10 ответов в теме

#1 Ripper Опубликовано 29 Октябрь 2011 - 15:13

Ripper
  • Свои
  • 497 Сообщений:
  • Павел Рустанович
Как называется неабстрактный класс (без неопределённых функций), предназначенный для наследования другими и не используемый никак иначе?

post-2756-0-28658900-1472313042.png


#2 Дей-Лак Опубликовано 29 Октябрь 2011 - 18:57

Дей-Лак
  • Свои
  • 596 Сообщений:
  • Николай Яковлев
Логично предположить, что никакого названия особого он не будет иметь. Ты же можешь создать его объект.
Опубликованное фото
Конституцию прочесть должен ты.

#3 KiberGus Опубликовано 29 Октябрь 2011 - 19:25

KiberGus
  • Genius loci
  • 6 561 Сообщений:
  • Алексей Гусейнов

Как называется неабстрактный класс (без неопределённых функций), предназначенный для наследования другими и не используемый никак иначе?

Он называется неправильно спроектированный класс. Если он ТОЛЬКО для наследования и не предназначается для прямого использования, то он должен быть абстракным.

Однако есть одно исключение: mixin. Но в C++ они могут быть реализованы только в виде классов с шаблонной базой, что несколько уменьшает возможности их применения.
Зато, обладая единственной в мире подводной орбитальной группировкой спутников глонасс...
gentoo.gif

#4 KiberGus Опубликовано 29 Октябрь 2011 - 22:01

KiberGus
  • Genius loci
  • 6 561 Сообщений:
  • Алексей Гусейнов
Если опишешь, что у тебя за класс такой, что он делает и как его должны использовать остальные, можно будет сказать больше. Но смысл в том, что если у тебя класс не абстрактный, то он полнофункциональный. Им можно пользоваться и он будет работать. И это обычный класс. А если им пользоваться нельзя, то и делать его создаваемым не правильно. Это значит, что у тебя в классе есть заглушки, которые не отловятся на этапе компиляции и, если кто-то им случайно воспользуется, программа будет падать уже в рантайме.
Зато, обладая единственной в мире подводной орбитальной группировкой спутников глонасс...
gentoo.gif

#5 Ripper Опубликовано 30 Октябрь 2011 - 4:02

Ripper
  • Свои
  • 497 Сообщений:
  • Павел Рустанович

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

Есть класс VideoFilterManager с функциями включения/выключения всяких фильтров (эффектов) и управления ими, а также protected функцией Process. через которую ему наследник передаёт по очереди кадры, а он применяет к ним свои эффекты.

А если им пользоваться нельзя, то и делать его создаваемым не правильно. Это значит, что у тебя в классе есть заглушки, которые не отловятся на этапе компиляции и, если кто-то им случайно воспользуется, программа будет падать уже в рантайме.

Ничего не упадёт, если создать экземпляр класса, просто некому будет его кормить через Process.

Я думал и о других вариантах реализации:
  • Функция Process public, и объект хранится внутри наследника.
    Но тогда не получится пользоваться функциями вкл/выкл фильтров извне.
  • Как звено конвеера. VideoFilterManager существует вне "наследника", получает от него кадры и передаёт их дальше.
    Тогда конвеер излишне усложняется, так как остальные звенья сильно отличаются (для них надо делать копии кадров, надо учитывать возможность прицепления нескольких звеньев одновременно и ещё по мелочи).

Изменено: Ripper, 30 Октябрь 2011 - 4:07

post-2756-0-28658900-1472313042.png


#6 KiberGus Опубликовано 30 Октябрь 2011 - 9:43

KiberGus
  • Genius loci
  • 6 561 Сообщений:
  • Алексей Гусейнов

Есть класс VideoFilterManager с функциями включения/выключения всяких фильтров (эффектов) и управления ими, а также protected функцией Process. через которую ему наследник передаёт по очереди кадры, а он применяет к ним свои эффекты.

Наследованеи - это самая сильная связность. По возможности, если агрегация нормально вписывается, лучше использолвать ее.

А ты не хочешь выкинуть manager вообще и ставить в конвеер фильтры? Получится намного проще. А то у тебя в каждом узле конвеера сидит сложное нечто, что умеет все-все-все и настраивается снаружи.
Зато, обладая единственной в мире подводной орбитальной группировкой спутников глонасс...
gentoo.gif

#7 Ripper Опубликовано 30 Октябрь 2011 - 11:15

Ripper
  • Свои
  • 497 Сообщений:
  • Павел Рустанович

Наследованеи - это самая сильная связность. По возможности, если агрегация нормально вписывается, лучше использолвать ее.

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

А ты не хочешь выкинуть manager вообще и ставить в конвеер фильтры? Получится намного проще. А то у тебя в каждом узле конвеера сидит сложное нечто, что умеет все-все-все и настраивается снаружи.

Тогда осложнится включение/выключение отдельных фильтров, а также

конвеер излишне усложняется, так как остальные звенья сильно отличаются (для них надо делать копии кадров, надо учитывать возможность прицепления нескольких звеньев одновременно и ещё по мелочи).


нечто, что умеет все-все-все и настраивается снаружи.

Может быть, моя ошибка в неправильной организации взаимодействия пользовательского интерфейса и программы? Я представляю GUI как нечто монолитное, настраивающее всё и вся снаружи. И с точки зрения GUI, как раз удобно, когда есть что-то умеющее всё-всё-всё и настраивающееся снаружи.

post-2756-0-28658900-1472313042.png


#8 KiberGus Опубликовано 30 Октябрь 2011 - 12:51

KiberGus
  • Genius loci
  • 6 561 Сообщений:
  • Алексей Гусейнов

Тогда осложнится включение/выключение отдельных фильтров, а также

Наоборот, упрощается. Если у тебя в конвеере находятся фильтры, то ты можешь либо убирать/добавлять их в конвеер. Либо включать/отключать их прямо в конвеере. Вместо кучи методов "включить фильтр такой-то" у тебя будет один метод: включить. Используй полиморфизм, не пытайся составить конвеер из одинаковых элементов, умеющих все.

Может быть, моя ошибка в неправильной организации взаимодействия пользовательского интерфейса и программы? Я представляю GUI как нечто монолитное, настраивающее всё и вся снаружи. И с точки зрения GUI, как раз удобно, когда есть что-то умеющее всё-всё-всё и настраивающееся снаружи.

Не удобно. Почитай про концепцию open close. У тебя получается, что чтобы добавить любой функционал к своей программе нужно переписывать GUI. Причем ты не можешь сделать подключаемые фильтры: GUI то монолитный. И чем больше фильтров, тем сложнее и больше GUI. Ты получишь переграженный большой класс, котоырй делает все.
Решение - каждому фильтру сделать widget с настройками этого фильтра. Если у фильтров есть общие настройки - вынести их в базовый интерфейс и сделать отдельные контролы, настраивающие эти свойства.
Зато, обладая единственной в мире подводной орбитальной группировкой спутников глонасс...
gentoo.gif

#9 St.ALKer Опубликовано 30 Октябрь 2011 - 16:46

St.ALKer
  • Свои
  • 59 Сообщений:
  • .
Наследоваться с целью получить возможность вызвать protected метод - это похоже на антипаттерн ;)

#10 KiberGus Опубликовано 30 Октябрь 2011 - 19:30

KiberGus
  • Genius loci
  • 6 561 Сообщений:
  • Алексей Гусейнов
Я советую написать интерфейс ivideostream аналогичный istream, интерйфейс ovideostream, аналогичный ostream. Сделать двойное наследование и получить videostream (это тот немногий случай, когда оно оправдано). Написать реализацию vediostream названную videopipe. Обязательно с буфером, чтобы сливающиеся ветки потоков могли работать с разным запаздыванием. Кадры передавать в виде легковесных оболочек над данными, тиа unique_ptr (auto_ptr в старом стандарте) или shared_ptr Сделать интерфейс Node имеющий методы size_t inputSize() - сколько входов имеет вершина setInput(size_t index, ivideostream& stream) - установить поток, из которого читать Аналогично с output. Если тебе нужны вешины с изменяющимся числом входов/выходов, надо еще подумать unique_ptr<widget> settingsWidget() - возвращает виджет с настройками этого узла. Обрати внимание, что коду который работает с узлом не нужно знать его тип и как его настраивать. Ему достаточно получить от конкретной реализации этот виджет и отобразить его. Виджет уже будет знать, как настраивать конкретный узел. string name() - имя, под которым отображать вершину. Опционально можно сделать иконки, цвета и т.п. Остается сделать поле, на котором можно отображать эти вершины (хранить их в boost::ptr_vector). Мышкой их таскать, вызывать диаог настройки и т.п. Коду, который это делает не нужно знать типы вершин, ему хватит базового класса. Мышкой же соединяем входные и выходные интерфейсы линиями - каждой линии соответсвует videopipe.
Зато, обладая единственной в мире подводной орбитальной группировкой спутников глонасс...
gentoo.gif

#11 Ripper Опубликовано 31 Октябрь 2011 - 4:38

Ripper
  • Свои
  • 497 Сообщений:
  • Павел Рустанович

Не удобно. Почитай про концепцию open close. У тебя получается, что чтобы добавить любой функционал к своей программе нужно переписывать GUI. Причем ты не можешь сделать подключаемые фильтры: GUI то монолитный. И чем больше фильтров, тем сложнее и больше GUI. Ты получишь переграженный большой класс, котоырй делает все.
Решение - каждому фильтру сделать widget с настройками этого фильтра. Если у фильтров есть общие настройки - вынести их в базовый интерфейс и сделать отдельные контролы, настраивающие эти свойства.

Я ушёл читать про SOLID, потом паттерны, а потом про виджеты (Qt).
как закончу, вернусь :)

Мышкой их таскать, вызывать диаог настройки и т.п. Коду, который это делает не нужно знать типы вершин, ему хватит базового класса.

Мышкой же соединяем входные и выходные интерфейсы линиями - каждой линии соответсвует videopipe.

В ffmpeg похожее реализовали, только без мышки (libavfilter).

post-2756-0-28658900-1472313042.png





1 пользователей читают эту тему

0 пользователей, 1 гостей, 0 невидимых