Джесс Либерти - Освой самостоятельно С++ за 21 день.
- Название:Освой самостоятельно С++ за 21 день.
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Джесс Либерти - Освой самостоятельно С++ за 21 день. краткое содержание
В книге широко представлены возможности новейшей версии программного продукта Microsoft Visual C++. Подробно описаны средства и подходы программирования современных профессиональных приложений. Материалы книги дополнены многочисленными демонстрационными программами, в процессе разработки которых максимально используются возможности программных инструментов Microsoft Visual Studio. Особое внимание уделено новинкам версии 6.0 и новейшим технологиям объектно-ориентированного программирования, включая использование библиотеки MFC и шаблонов классов, а также создание связанных списков. Отдельное занятие посвящено вопросам объектно-ориентированного анализа и проектирования приложений. Подробно рассмотрены все средства и подходы конструирования собственных пользовательских классов.
Книга рассчитана на широкий круг читателей, интересующихся современными проблемами программирования.
Освой самостоятельно С++ за 21 день. - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Во время выполнения программы происходит тестирование указателя базового класса. Если устанавливается, что текущий объект, на который ссылается указатель базового класса, в действительности является объектом производного класса, то с этим объектом связывается указатель производного класса. В противном случае указатель производного класса становится нулевым. Пример использования этого подхода показан в листинге 13.2.
Листинг 13.2. Приведение вниз
1: // Листинг 13 2 Использование оператора dynamic_cast
2: // Использование rtti
3:
4: #include
5: enum TYPE { HORSE, PEGASUS };
6:
7: class Horse
8: {
9: public
10: virtual void Gallop(){ cout << "Galloping...\n"; }
11:
12: private:
13: int itsAge;
14: };
15:
16: class Pegasus : public Horse
17: {
18: public:
19:
20: virtual void Fly() { cout << "I can fly! I can fly! I can fly!\n"; }
21: };
22:
23: const mt NumberHorse = 5,
24: int main()
25: {
26: Horse* Ranch[NumberHorse];
27: Horse* pHorse;
28: int choice,i,
29: for (i=0; KNumberHorse, i++)
30: {
31: cout << "(1)Horse (2)Pegasus: ";
32: cin >> choice;
33: if (choice == 2)
34: pHorse = new fegasus;
35: else
36: pHorse = new Horse;
37: Rancfi[i] = pHorse,
38: }
39: cout << "\n";
40: for (i=0; a
41: {
42: Pegasus *pPeg = dynamic_cast< Pegasus *> (Ranch[i]);
43: if (pPeg)
43: pPeg->Fly();
44: else
45: cout << "Just a horse\n";
46:
47: delete Ranch[i];
48: }
49: return 0;
50: }
Результат:
(1)Horse (2)Pegasus: 1
(1)Horse (2)Pegasus: 2
(1)Horse (2)Pegasus: 1
(1)Horse (2)Pegasus: 2
(1)Horse (2)Pegasus: 1
Just a horse
I can fly! I can fly! I can fly!
Just a horse
I can fly! I can fly! I can fly!
Just a horse
Вопросы и ответы
Во время компиляции появляется сообщение об ошибке C4541: 'dynamic_cast' used on polymorphic type 'class Horse' with/GR-; unpredictable behavior may result
Как поступить?
Это сообщение MFC действительно может смутить начинающего программиста. Чтобы устранить ошибку, выполните ряд действий.
1. Выберите в окне проекта команду Project->Settings.
2. Перейдите к вкладке С/C++.
3. Выберите в раскрывающемся списке Category опцию C++ Language
4. Установите Enable Runtime Type Information (RTTI).
5. Повторно скомпилируйте весь проект.
Анализ:Этот пример программы также будет вполне работоспособным. Метод Fly() не связан напрямую с классом Horse и не будет вызываться для обычных объектов этого класса. Он выполняется только для объектов класса Pegasus, но для этого программе приходится каждый раз анализировать, с каким объектом связан указатель, и приводить текущий указатель к типу производного класса.
Все же следует признать, что программы с приведением типа объектов выглядят несколько неуклюже и в них легко запутаться. Кроме того, данный подход идет в разрез с основной идеей полиморфизма виртуальных функций, поскольку выполняемость метода теперь зависит от приведения типа объекта во время выполнения программы.
Добавление объекта в два списка
Другая проблема состоит в том, что при объявлении Pegasus как объекта типа Horse становится невозможным добавить его в список объектов класса Bi rd. Приходилось то переносить функцию Fly() вверх по иерархии классов, то выполнять приведение указателя, но так и не удалось в полной мере достичь необходимого функционирования программы.
Таким образом, придерживаясь только одиночного наследования, оказалось невозможным элегантно решить эту проблему. Можно перенести все три функции — Fly(), Whinny() и Gallop() — в базовый класс Animal, общий для двух производных классов Bird и Horse. В результате вместо двух списков объектов для классов Bird и Horse получится один общий список объектов класса Animal. Недостаток метода состоит в том, что базовый класс принимает на себя слишком много функций.
В качестве альтернативы можно оставить методы там, где они есть, и заняться приведением типов объектов классов Horse, Bird и Pegasus, но результат в конечном итоге будет еще хуже!
Рекомендуется: Переносите вверх по иерархии классов функции общего использования. Избегайте использовать коды, основанные на определении типов объектов во время выполнения программы. Вместо этого используйте виртуальные методы, шаблоны и множественное наследование.
Не рекомендуется: Не переносите вверх по иерархии классов интерфейсы производных классов.
Множественное наследование
Существует возможность производить новые классы более чем от одного базового класса. Такой процесс называется множественным наследованием. Чтобы произвести подобный класс, базовые классы в объявлении разделяются запятыми. В листинге 13.3 класс Pegasus объявлен таким образом, что наследует свойства двух базовых классов — Bird и Horse. Затем программа добавляет объект Pegasus в списки объектов обоих классов.
Листинг 13.3. Множественное наследование
1: // Листинг 13.3. Множественное наследование.
2: // Множественное наследование
3:
4: #include
5:
6: class Horse
7: {
8: public:
9: Horse() { cout << "Horse constructor... "; }
10: virtual ~Horse() { cout << "Horse destructor... "; }
11: virtual void Whinny() const { cout << "Whinny!... "; }
12: private:
13: int itsAge;
14: };
15:
16: class Bird
17: {
18: public:
19: Bird() { cout << "Bird constructor... "; }
20: virtual ~Bird() { cout << "Bird destructor... "; }
21: virtual void Chirp() const { cout << "Chirp... "; }
22: virtual void Fly() const
23: {
24: cout << "I can fly! I can fly! I can fly! ";
25: }
26: private:
27: int itsWeight;
28: };
29:
30: class Pegasus : public Horse, public Bird
31: {
32: public:
33: void Chirp() const { Whinny(); }
34: Pegasus() { cout << "Pegasus constructor... "; }
35: ~Pegasus() { cout << "Pegasus destructor... "; }
36: };
37:
38: const int MagicNumber = 2;
39: int main()
40: {
41: Horse* Ranch[MagicNumber];
42: Bird* Aviary[MagicNumber];
43: Horse * pHorse;
44: Bird * pBird;
45: int choice,i;
46: for (i=0; i
47: {
48: cout << "\n(1)Horse (2)Pegasus: ";
49: cin >> choice;
50: if (choice == 2)
51: pHorse = new Pegasus;
52: else
53: pHorse = new Horse;
54: Ranch[i] = pHorse;
55: }
56: for (i=0; i
57: {
58: cout << "\n(1)Bird (2)Pegasus: ";
59: cin >> choice;
60: if (choice == 2)
61: pBird = new Pegasus;
62: else
63: pBird = new Bird;
64: Aviary[i] = pBird;
65: }
66:
67: cout << "\n";
68: for (i=0; i
69: {
70: cout << "\nRanch[" << i << "]:
71: Ranch[i]->Whinny();
72: delete Ranch[i];
73: }
74:
75: for (i=0; i
76: {
77: cout << "\nAviary[" << i << "]
78: Aviary[i]->Chirp();
79: Aviary[i]->Fly();
80: delete Aviary[i];
81: }
82: return 0;
83: }
Результат:
(1)Horse (2)Pegasus: 1
Horse constructor...
(1)Horse (2)Pegasus: 2
Horse constructor... Bird constructor... Pegasus constructor...
(1)Bird (2)Pegasus: 1
Bird constructor...
(1)6ird (2)Pegasus: 2
Horse constructor... Bird constructor... Pegasus constructor...
Ranch[0]: Whinny!... Horse destructor...
Ranch[1]: Whinny!... Pegasus destructor... Bird destructor...
Horse destructor...
Aviary[0]: Chirp... I can fly! I can fly! I can fly! Bird destructor...
Aviary[1]: Whinny!... I can fly! I can fly! I can fly!
Pegasus destructor... Bird destructor... Horse destructor...
Анализ:В строках 6—14 объявляется класс Horse. Конструктор и деструктор выводят на экран сообщения о своей работе, а метод Whinny() печатает Whinny! (И-го-го).
Класс Bird объявляется в строках 16—28. В дополнение к своим конструктору и деструктору этот класс содержит два метода: Chirp() и Fly(), каждый из которых выводит на экран соответствующие сообщения. В реальных программах эти методы могут воспроизводить определенный звуковой файл или управлять анимационными эффектами на экране.
Читать дальшеИнтервал:
Закладка: