C++ для начинающих Виртуальные функции Продолжение знакомства Динамический полиморфизм

В продолжении темы начала знакомства с виртуальными функциями пишу этот материал. Несмотря на то, что я описал первопричину использования виртуальных функций, этого явно мало. В литературе для лучшего понимания виртуальных функций используют пример, в котором создается массив объектов. Это не обычный массив объектов, а каждый элемент массива имеет объект различного типа. Вспомним что такое класс. Класс — это пользовательский тип данных. Значит каждый новый класс это новый тип.

Давайте вспомним одно свойство массива. Массив — это набор однотипных данных. Может показаться, что использование наследования и виртуальных функций немного нарушает такое определение. Если размышлять, то можно прийти к мыслям: «Если массив содержит данные только одного типа, то значит в один массив объекты разных типов мне поместить не удастся». Это совершенно верные мысли. Несмотря на это любой самый обычный массив можно построить таким образом, что элементы, обрабатываемые с помощью него будут иметь различные типы. Может показаться, что я противоречу сам себе, но вовсе нет. Для того, чтобы построить такой массив с элементами различных типов используют массив указателей. Каждый элемент такого массива — это указатель.

Перехожу от слов к делу.
Задача: Создать массив объектов класса млекопитающие

Предположим у нас есть 3 вида млекопитающих и остальные неизвестные нам. Нам известны собака, кот и свинья. Каждое млекопитающее издает собственные звуки. Кот мяукает, собака лает, свинья хрюкает.

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

Код C++ Виртуальные функции Динамический полиморфизм

Применены приемы наследования. Создано три потомка из основного класса. Каждый потомок — это известное нам млекопитающее

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

Код С++ Виртульные функции Динамический полиморфизм

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

Посмотрев и поняв работу примера вы лучше поймете описание полиморфизма: Один класс, множество методов

Основная идея использования полиморфизма: «Независимо от возрастания объемов кода и сложности программы, ко всем объектам, выведенным из базового класса, можно использовать один единственный общий способ доступа для каждого объекта, независимо от того что поведения этих объектов различны»

Все комментарии на сайте проверяются, поэтому ваш комментарий может появиться не сразу. Для вставки кода в комментарий используйте теги: [php]ВАШ_КОД[/php]

3 комментария: C++ для начинающих Виртуальные функции Продолжение знакомства Динамический полиморфизм

  • Serge говорит:

    Спасибо, мне статья понравилась и пример доступный. Сайт добавлю в закладки)




    0



    0
  • Gen говорит:

    У вас везде написано

    а надо

    Т мне не понятно зачем массив на
    5 элементов? Ведь в нулевой мы ничего не записываем?А красоту можно и так навести.

    Автор сайта отвечает:
    Вот правильный код

    Теперь объясняю конкретнее.
    Пусть животных 5 — это обозначает, что всего 5 животных. Эти 5 животных — это животные любого вида. Комбинаций из 5 животных достаточно большое число. Например может быть 4 коровы и 1 свинья, а может 3 собаки, 1 свинья, 1 собака и так любая комбинация из видов животных. Массив создается под всех животных. В примере всего видов животных 3 (3 класса). Количество всех животных абсолютно любое (сколько вообще животных, а не сколько классов, столько ячеек в массиве), а вот видов животных строго определенное количество. Видов животных 3, значит для каждого вида свое поведение.(3 вида животных = 3 типа поведения, не больше не меньше). Класс здесь обозначает только поведение, массив немного напоминает Загон.

    Надеюсь пояснее стало.
    (сходу я неправильно написал, позднее изменил эту запись, голова забита другим, поэтому извините если вас запутал начальными неправильными ответами)
     
    Как должно работать?
    Вводим несколько чисел
    1,3,1,2,2 (это идентификатор животного)
    =========================
    1 = Собака —> Поведение гав гав
    3 = Свинья —> Поведение хрюн хрюн
    1 = Собака —> Поведение гав гав
    2 = Кот —> Поведение мяу мяу
    2 = Кот —> Поведение мяу мяу
    =========================
    пример работы программы

    Gen говорит:
    Да разобрался.Переписал вручную и все заработало как надо.А в моем коде пришлось несколько упростить себе задачу,а ошибок нет, иначе где бы я взял скрин.Спасибо.




    0



    0
  • Gery говорит:
    #include <iostream>
    #include <stdlib.h>
    using namespace std;
    /*КЛАСС-РОДИТЕЛЬ*/
    class Mammal
    {
    public:
    	virtual void Speak() { cout << "Mammal Speakn"; } //Виртуальный метод. Звук неизвестного млекопитающего
    };
    
    /*СОЗДАЕМ ПОДКЛАСС МЛЕКОПИТАЮЩЕГО*/
    class Dog :public Mammal
    {
    public:
    	void Speak() { cout << "GavGav/n"; } //Виртуальный метод. Собака лает
    };
    
    /*СОЗДАЕМ ПОДКЛАСС МЛЕКОПИТАЮЩЕГО*/
    class Cat :public Mammal
    {
    public:
    	void Speak() { cout << "Meow/n"; } //Виртуальный метод. Кот мяукает
    };
    
    /*СОЗДАЕМ ПОДКЛАСС МЛЕКОПИТАЮЩЕГО*/
    class Pig :public Mammal
    {
    public:
    	void Speak() { cout << "HruHr/n"; } //Виртуальный метод. Свинья хрюкает
    };
    /*==================*/
    void main()
    {
    	system("CLS");
    	Mammal *Array[5]; //Объявляем массив указателей на класс Млекопитающие
    	Mammal *ptr;  //Объявили указатель на класс Млекопитающие
    
    	int MyWibor; //Переменная для выбора пользователем
    	//Небольшое украшательство
    	setlocale(LC_ALL, "Russian");
    	cout << "Выбери млекопитающее: \n";
    	cout << "1 - СОБАКА\n";
    	cout << "2 - КОШКА\n";
    	cout << "3 - СВИНЬЯ\n\n";
    
    	//С помощью цикла заполняем массив указателями на объекты
    	for (int i = 0; i < 5; i++) //Пусть млекопитающих пять
    	{
    		cout << i + 1 << ". "; //Номер текущего млекопитающего
    		cin >> MyWibor;  //Пользователь вводит число
    
    		switch (MyWibor) //Основываясь на введенном числе выделяем память для нужного млекопитающего
    		{
    		case 1:
    			ptr = new Dog; //Если один - выделяем память для создания класса Собака
    			break;
    		case 2:
    			ptr = new Cat; //Если два - выделяем память для создания класса Кошка
    			break;
    		case 3:
    			ptr = new Pig; //Если три - выделяем память для создания класса Свинья
    			break;
    		default:
    			ptr = new Mammal; //Если что-то другое - выделяем память для создания класса Млекопитающее
    			break;
    		}//switch    Выбор сделан
    
    		Array[i] = ptr; //Выбор сделан, память выделена, заносим указатель на созданный объект в массив
    	} //Цикл for завершен
    
    	for (int g = 0; g < 5; g++) Array[g]->Speak(); //Проходим по всему циклу и вызываем метод Speak для каждого элемента
    
    	for (int i = 0; i < 5; i++) delete Array[i]; //Мы выделяли память, значит нужно её освободить.
    
    	system("pause");
    }

    Поправил все косяки.




    0



    0

Добавить комментарий

Ваш e-mail не будет опубликован.

Поиск

 
     

Случайная книга в электронном формате

Яндекс.Метрика
НАГРАДИ АВТОРА САЙТА
WEBMONEY
R375024497470
U251140483387
Z301246203264
E149319127674

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

Выражаю свою признательность

  • Максиму очень признателен за указание на мои ошибки и неточности.
  • Sergio ===> за оказание помощи в исправлении моих ошибок
  • Gen ===> за правильное стремление помочь другим новичкам и выявления моих ошибок