реклама на сайте
подробности

 
 
> Помогите разобраться с классами С++, вопрос с построением иерархии
Legotron
сообщение Apr 23 2007, 09:57
Сообщение #1


инопланетянин
***

Группа: Свой
Сообщений: 236
Регистрация: 24-12-06
Из: Питер
Пользователь №: 23 832



Добрый день!

Я занимаюсь написанием графического интерфейса для LCD монитора на 16-разрядном микроконтроллере XC167.

Для графики пытаюсь использовать ООП.
Опыт работы с ООП совсем небольшой.

У меня есть некоторые недопонимания с построением иерархии классов.
Например, хотелось бы создать класс TFont. От него наследовать TChar (все что касается отображения символов). Далее от TChar - TString.
Но с другой стороны рисования символа состоит из рисования точек. А все, что связано с точками (Line, Circle ...) растет от класса TPoint.
Как тут быть? Ведь TFont совсем не связан логически с TPoint (как мне кажется).
Использовать множественное наследование? пересмотреть TFont - TChar? Отказаться от связи TChar с классами иерархии TPoint?

Пожалуйста пролейте свет на этот вопрос.

P.S. Не могли бы вы посоветовать мне какие-нибудь книги или статьи с жизненными примерами ООП. А то, в основном, все примеры которые мне попадались какие-то слишком академичные.

Заранее благодарен! smile.gif
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Freeze Anti
сообщение Apr 23 2007, 10:39
Сообщение #2


Частый гость
**

Группа: Новичок
Сообщений: 153
Регистрация: 29-03-07
Из: Саратов
Пользователь №: 26 613



Я бы на вашем месте пошел по такому пути... Поставил бы на компьютере C++Builder, затем посмотрел, как там организована иерархия классов, а затем попытался бы портировать это дело в ту версию С++, которую использую... Кстати, если я не ошибаюсь, В Билдере класс TString никак не связан с выдачей инфомации на экран... Это чуть ли не просто нуль-теминальная строка (В С++ изначально есть работа только с символами char, а строка символов - это одномерный массив, но работать так не очень удобно, поэтому есть класс TString... Вывод символьных данных и графической информации отличается... Нам нужно будет создать два разных объекта... А в общем - покопайтесь сами - найдете много интересного, хотя Некоторые вещи скрыты архитектурой Windows, но вам необходима именно иерархия объектов...


--------------------
!!! All you need is LOVE !!!
Go to the top of the page
 
+Quote Post
dxp
сообщение Apr 23 2007, 11:12
Сообщение #3


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(Freeze Anti @ Apr 23 2007, 14:39) *
Я бы на вашем месте пошел по такому пути... Поставил бы на компьютере C++Builder, затем посмотрел, как там организована иерархия классов, а затем попытался бы портировать это дело в ту версию С++, которую использую...

Вот ни в коем случае не надо для этого использовать CBuilder - там весь ГУИ основан на VCL, которая заимствована из Delphi и, соответственно, реализована на борландовском Паскале (если это можно так назвать smile.gif ). Включая ту же TString - компонент VCL. VCL никакого отношения к языку С++ не имеет.

Правильная подсказка - взять хорошую книжку по языку и по ООП (см выше).


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
Bogatyr
сообщение Apr 26 2007, 10:58
Сообщение #4


Участник
*

Группа: Новичок
Сообщений: 25
Регистрация: 24-03-07
Пользователь №: 26 466



Извиняюсь за глупый вопрос. Но разве ООП и микроконтроллеры дружат? Я думал, что для микроконтроллеров существуют максимум компиляторы С, но никак ни С++?
Go to the top of the page
 
+Quote Post
dxp
сообщение Apr 27 2007, 14:49
Сообщение #5


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(Bogatyr @ Apr 26 2007, 14:58) *
Извиняюсь за глупый вопрос. Но разве ООП и микроконтроллеры дружат? Я думал, что для микроконтроллеров существуют максимум компиляторы С, но никак ни С++?

Вполне дружат. А что этому мешает? В чем С++ принципиально более требователен к ресурсам по сравнению с С при реализации той же функциональности?

Итого, С++ есть даже для 8-битного AVR и прекрасно работает. Конечно, там не полный перечень фич С++ поддерживается - не поддерживаются тяжелые и реально ненужные механизмы языка - исключения, RTTI. Множественное наследование также не поддерижвается, но это, видимо, от того, что не очень надо. Основные возможности - классы, перегрузка функций и операторов, шаблоны и т.д., все это есть и замечательно работает.

Цитата(Legotron @ Apr 27 2007, 17:37) *
Непроизводительные издержки С++ в основном в виртуальном механизме.

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

Цитата(Legotron @ Apr 27 2007, 17:37) *
Мощный МК их способен с лихвой покрыть!

И не мощный тоже. smile.gif То же AVR прекрасно с этим справляется.


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
Legotron
сообщение Apr 27 2007, 15:57
Сообщение #6


инопланетянин
***

Группа: Свой
Сообщений: 236
Регистрация: 24-12-06
Из: Питер
Пользователь №: 23 832



Цитата(dxp @ Apr 27 2007, 15:49) *
Тут есть некий оверхед на организацию механизма, но он объективно необходим. Ведь для оценки оверхеда (и вообще, оверхед ли это) надо сравнить с реализацией тоже функциональности традиционными (Сишными) средствами. Уверяю Вас, что руками лучше сделать вряд ли получится.

Абсолютно с вами согласен.
Но всё-таки можно и switch - case конструкцией обойтись(в некоторых случаях). Хотя по сравнению с механизмом полиморфизма она кажется несовершенной.

Неболшой оффтопик:
У меня возник такой вопрос:

Есть класс А. Он наследутся классом В.
В обеих классах есть виртуальная функция Draw.
Код
class A {
...
virtual void Draw();
...
};
class B : public A {
...
virtual void Draw();
...
};

A *PObjA;             // указатель на базовый класс
B ObjB;                // Создан объект класса В

void * Ptr;

Ptr = (A *)PObjA;  // может лишнее
Ptr = &ObjB;          
Ptr->Draw();         // будет ли вызвана ф-ция Draw класса В?

Можно ли вообще так сделать?
Этот вопрос возник из желания сделать универсальный связанный список с полем Item типа void * для любых объектов?
smile.gif
Go to the top of the page
 
+Quote Post
dxp
сообщение Apr 27 2007, 16:56
Сообщение #7


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(Legotron @ Apr 27 2007, 19:57) *
Абсолютно с вами согласен.
Но всё-таки можно и switch - case конструкцией обойтись(в некоторых случаях). Хотя по сравнению с механизмом полиморфизма она кажется несовершенной.

Ну, реализовать функциональность можно разными путями, но switch/case далеко не всегда предоставляют адекватную замену. Например, можно поставлять библиотеку с функциями, но саму реализацию скрыть внутри. А пользователь вызывает вроде одну и ту же функцию (виртуальную), а реализация может быть разной. По этому принципу, например, строятся СОМ интерфейсы в винде.


Цитата(Legotron @ Apr 27 2007, 19:57) *
Есть класс А. Он наследутся классом В.
В обеих классах есть виртуальная функция Draw.
Код
class A {
...
virtual void Draw();
...
};
class B : public A {
...
virtual void Draw();
...
};

A *PObjA;             // указатель на базовый класс
B ObjB;                // Создан объект класса В

void * Ptr;

Ptr = (A *)PObjA;  // может лишнее
Ptr = &ObjB;          
Ptr->Draw();         // будет ли вызвана ф-ция Draw класса В?

Можно ли вообще так сделать?
Этот вопрос возник из желания сделать универсальный связанный список с полем Item типа void * для любых объектов?
smile.gif

"Ptr = (A *)PObjA; // может лишнее" - однозначно лишнее, хотя это ничего не меняет. smile.gif

Работать не будет. Ptr имеет тип void * - это просто хранилище для адресов, а чтобы можно было работать с объектом класса, указатель на него должен "знать" о строении (структуре) класса. Вот

A *pA;
B *pB;

тут pA "знает" все о классе А, а pB - все о классе В. Поэтому будет работать вызов:

A *p = &ObjB;
p->Draw();

Вообще, использование void * и ручных преобразований типов - есть плохая практика, старайтесь ее избегать. Существует очень ограниченное количество случаев, где без этого не обойтись, но их стараются "обернуть", чтобы это не лежало на поверхности.

Что касается универсальности в отношении разных типов, то, возможно, Вам помогут шаблоны. Т.е. тип объекта задавать как параметр шаблона.


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 25th July 2025 - 19:23
Рейтинг@Mail.ru


Страница сгенерированна за 0.01433 секунд с 7
ELECTRONIX ©2004-2016