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

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

    Задача:

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

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

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

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

  1. Serge:

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

  2. 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 говорит:
    Да разобрался.Переписал вручную и все заработало как надо.А в моем коде пришлось несколько упростить себе задачу,а ошибок нет, иначе где бы я взял скрин.Спасибо.

  3. 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");
    }

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

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Поиск

 
     

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

https://www.litres.ru/tatyana-pavlovskaya/c-c-strukturnoe-i-obektno-orientirovannoe-programmirovanie-praktikum-586035/?lfrom=15589587
Яндекс.Метрика