123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- // Темы:
- // Простое наследование. Виртуальные функции. Абстрактные классы.
- // Битовые поля.
- #include "General.h"
- #include <iostream>
- #include <tchar.h>
- #define stop __asm nop
- int _tmain(int argc, _TCHAR* argv[])
- {
- //Задание 1.Массив объектов класса.
- {
- //Объявите и проинициализируйте массив ar из объектов типа MyString.
- //Замените размер const int N=5; , не изменяя список инициализаторов.
-
- //const int N=3;
- const int N = 5;
- MyString str1[N] = { MyString("First"), MyString("Second"), MyString("Third")};
-
- //Проверка - печать строк-членов класса
- for (int i = 0; i < N; i++)
- {
- std::cout << str1[i].GetString() << std::endl;
- }
- }
- stop
- //Задание 2.Массив указателей на объекты класса.
- {
- //Объявите и проинициализируйте массив arPtr из N
- //указателей на объекты типа MyString (сами объекты создаются динамически!).
- //Замените размер const int N=5; , не изменяя список инициализаторов.
-
- //const int N=3;
- const int N = 5;
- MyString* arPtr[N] = { new MyString("First ptr"), new MyString("Second ptr"), new MyString("Third ptr") };
- //Печать строк-членов класса
- for (int i = 0; i < N; i++)
- {
- if(arPtr[i])
- {
- std::cout << (*arPtr[i]).GetString() << std::endl;
- }else{ std::cout << "nullptr - Empty string" << std::endl; }
- }
- }
- stop
- //Задание 3.Простое наследование.Аргументы конструктора,
- // передаваемые в базовый класс.
- //Создайте иерархию классов:
- //базовый класс Shape (который описывает любую фигуру)
- //и два производных класса Rect и Circle.
- //Подумайте: какие данные и методы нужно ввести в базовый
- //и производные классы (например, любую фигуру можно сделать
- //цветной => в базовом классе можно ввести переменную, которая
- //будет определять цвет фигуры.
- //Подсказка: для хранения цвета объявите перечисление (RED,GREEN,BLUE...);
- //В конструкторах производных классов предусмотрите передачу
- //параметра-цвета конструктору базового класса.
- //При создании и уничтожении объекта производного типа определите
- //последовательность вызовов конструкторов и деструкторов базового
- //и производного классов
- Shape Shape1;
- Shape Shape2(RED);
- Rect Rect1;
- Rect Rect2(1);
- Rect Rect3(1,2,3,4);
- Rect Rect4(1, 2, 3, 4, GREEN);
- Circle Circle1;
- Circle Circle2(5);
- Circle Circle3(5, 3, 1, BLUE);
- stop
- //////////////////////////////////////////////////////////////////////
- //Задание 4.Виртуальные функции.
- //4а) Модифицируйте классы Shape,Rect и Circle:
- //добавьте в каждый класс public метод void WhereAmI().
- //Реализация каждой функции должна выводить сообщение
- //следующего вида "Now I am in class Shape(Rect или Circle)".
- //Выполните приведенный фрагмент, объясните результат.
- {
- Shape s(RED);
- Rect r(1, 2, 3, 4, GREEN);
- Circle c(5, 3, 1, BLUE);
-
- //Метод какого класса вызывается в следующих строчках???
- s.WhereAmI(); // Shape (вызов формируется на этапе компиляции, как для обычного метода класса)
- r.WhereAmI(); // Rect
- c.WhereAmI(); // Circle
- stop
- Shape* pShape = &s;
- Shape* pRect = &r;
- Shape* pCircle = &c;
- pShape->WhereAmI(); // Shape (раннее связывание, т.к. указатель базового типа, во всех случаях будет вызван метод базового класса)
- pRect->WhereAmI(); // Shape (не имеет значение какого типа объект)
- pCircle->WhereAmI(); // Shape
- stop
- //Заполните ... согласно комментариям
- Shape& rShape = s; //псевдоним s (тип переменной Shape&)
- Shape& rRect = r; //псевдоним r
- Shape& rCircle = c; //псевдоним c
- rShape.WhereAmI(); //вызов посредством rShape Shape
- rRect.WhereAmI(); //вызов посредством rRect Shape
- rCircle.WhereAmI(); //вызов посредством rCircle Shape
- stop
- }
- //4б) Добавьте в базовый и производные классы виртуальный
- // метод WhereAmIVirtual(). По аналогии с 4а вызовите
- // виртуальный метод посредством объектов, указателей и
- // ссылок, определенных в предыдущем фрагменте.
- //Выполните новый фрагмент, объясните разницу.
- {
- Shape s(RED);
- Rect r(1, 2, 3, 4, GREEN);
- Circle c(5, 3, 1, BLUE);
- //Метод какого класса вызывается в следующих строчках (вызов формируется на этапе компиляции, как для обычного метода класса)
- s.WhereAmIVirtual(); // Shape
- r.WhereAmIVirtual(); // Rect
- c.WhereAmIVirtual(); // Circle
- stop
- Shape* pShape = &s;
- Shape* pRect = &r;
- Shape* pCircle = &c;
- pShape->WhereAmIVirtual(); // Shape (косвенно, посредством таблицы виртуальных функций)
- pRect->WhereAmIVirtual(); // Rect
- pCircle->WhereAmIVirtual();// Circle
- stop
- //Заполните ... согласно комментариям
- Shape& rShape = s; //псевдоним s
- Shape& rRect = r; //псевдоним r
- Shape& rCircle = c; //псевдоним c
- rShape.WhereAmIVirtual(); //вызов посредством rShape Shape (косвенно, посредством таблицы виртуальных функций)
- rRect.WhereAmIVirtual(); //вызов посредством rRect Rect
- rCircle.WhereAmIVirtual(); //вызов посредством rCircle Circle
- stop
- }
- //////////////////////////////////////////////////////////////////////
- //Задание 5.Виртуальные деструкторы.
- //Модифицируйте классы:
- //a) введите соответствующие
- // деструкторы (без ключевого слова virtual).
- //Реализация каждого деструктора
- //должна выводить сообщение следующего вида
- // "Now I am in Shape's destructor!" или
- // "Now I am in Rect's destructor!"
- //Выполните фрагмент. Объясните результат.
- // b) Добавьте в объявление деструкторов ключевое слово virtual
- //Выполните фрагмент.Объясните разницу.
-
- //Подумайте: какие конструкторы вызываются в следующей строке?
- //Если в разработанных классов каких-то конструкторов
- //не хватает - реализуйте
- //Если Вы считаете, что в приведенном фрагменте чего-то
- //не хватает - добавьте
- Rect r(1,2,3,4);
- Shape* ar[]={new Shape(r), new Rect(r), new Circle(r), new Circle()};
- //Вызовите для каждого элемента массива метод WhereAmIVirtual()
-
- for (int i = 0; i < (sizeof(ar) / sizeof(ar[0])); i++)
- {
- ar[i]->WhereAmIVirtual();
- delete ar[i];
- }
- stop
- //Задание 6*. В чем заключается отличие 1) и 2)
- {
- Shape* pShapes = new Rect[10];//1) одномерный динамический массив указателей типа Shape на обьекты типа Rect
- Rect* pRects = new Rect[10];//2) одномерный динамический массив указателей типа Rect на обьекты типа Rect
- //Попробуйте вызвать метод WhereAmIVirtual() для каждого элемента обоих массивов -
- //в чем заключается проблема???
- for (int i = 0; i < 10; i++)
- {
- pRects[i].WhereAmIVirtual();
- }
- /*
- for (int i = 0; i < 10; i++)
- {
- pShapes[i].WhereAmIVirtual(); //проблема на второй итерации, указатель базового класса, сдвиг???
- }
- */
-
- //Освободите динамически захваченную память
-
- delete []pShapes; //неверный сдвиг, могут быть нюансы
- delete[]pRects;
-
- }
- //////////////////////////////////////////////////////////////////////
- //Задание 7.Виртуальные функции и оператор разрешения области видимости.
- {
- Rect r(1,2,3,4);
- Shape* p = &r;
- p->WhereAmIVirtual();//Rect
- stop
-
-
- //4a Оператор разрешения области видимости.
- //Посредством объекта r и указателя p вызовите виртуальную функцию
- //WhereAmIVirtual()класса Shape
- p->Shape::WhereAmIVirtual();//Shape
- stop
- }
- //////////////////////////////////////////////////////////////////////
- //Задание 8.Чисто виртуальные функции.
- //Введите в базовый класс метод void Inflate(int); Подумайте:
- //можно ли реализовать такой метод для базового класса? => как его нужно объявить.
- //Реализуйте этот метод для производных классов.
- {
- Rect r(1,2,3,4);
- Shape* p = &r;
- p->Inflate(5);
- Circle c(1,2.3);
- p = &c;
- p->Inflate(5);
- }
- //////////////////////////////////////////////////////////////////////
- //Задание 9. Создайте глобальную функцию, которая будет принимать любое
- //количество указателей на строки, а возвращать объект MyString,
- //в котором строка будет конкатенацией параметров
- MyString res = concatenation("hello","i'm","Svetlana",nullptr);
- stop
- ////////////////////////////////////////////////////////////////////////
- /*
- //Задание 10.Объединения (union) C++. Битовые поля.
- //1.
- //Создайте следующие классы для различных представлений значений байта:
- //Bin - для двоичного представления
- //Hex - для шестнадцатерчного представления
- //Oct - для восьмеричного представления.
- //Подсказка 1: - для удобства используйте битовые поля.
- //Подсказка 2: - конструкторов в таких вспомогательных классах быть не должно,
- //так как все они будут членами объединения (union).
- //2.
- //В каждом классе введите метод Show, который должен выводить значение в
- //соответствующем виде
- //3.
- //Посредством объединения MyByte предоставьте пользователю возможность манипулировать
- //одним и тем же значением по-разному:
- //а) выводить: десятичное, шестнадцатеричное, восьмеричное, двоичное значение байта
- // а также символ, соответствующий хранимому значению (если есть соответствие);
- //б) выводить отдельные (указанные посредством параметра) шестнадцатеричные,
- // восьмеричные, двоичные цифры;
- //в) изменять отдельные двоичные, восьмеричные или шестнадцатеричные цифры;
- MyByte byte(0x1f);
- byte.ShowHex();
- byte.ShowBin();
- //...
- */
- return 0;
- }//endmain
|