Полиморфизм и статика в C++ Учебное пособие «Переход с языка C на C++ и программирование на C++ в Unreal Engine»③

Предисловие:

Полиморфизм буквально означает несколько форм.

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

полиморфизм

1. Перезаписать

В C++ подклассы могут наследовать код родительского класса, и на этом основании некоторые методы родительского класса могут быть перезаписаны для выполнения функций, отличных от родительского класса.

Переопределенный метод должен иметь то же имя функции, что и переопределенный метод, а также должны быть одинаковыми типы параметров и типы возвращаемых значений.

Например:

Результат:

Помимо методов-членов (также известных как функции-члены), которые могут быть переопределены, переменные-члены также могут быть переопределены.

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

Например:

Результат:

В то же время мы также обнаружили, что когда C++ создает экземпляр подкласса, он сначала вызывает конструктор своего родительского класса, а затем вызывает свой собственный конструктор.

Дополнительный контент: Разница между переписыванием и перегрузкой:

Перегрузка (примечание: читай chong load, а не zhong load, английское название — перегрузка)

Относится к нескольким функциям с одним и тем же именем, объявленным в одной и той же доступной области с разными списками параметров (разные типы, числа и порядок параметров), вызываемая функция определяется в соответствии со списком параметров, и при перегрузке не учитывается возвращаемый результат. тип функции.

Мы можем позволить методам-членам с одним и тем же именем иметь множество различных списков параметров посредством перегрузки.При их использовании мы можем вызывать разные методы в соответствии с разными параметрами для выполнения одной и той же функции.

Конструктор класса также может быть перегружен, и могут использоваться разные методы построения в соответствии с разными типами параметров, но деструктор не может, потому что деструктор не может иметь никаких формальных параметров.

Пример использования перегрузки:

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

2. Виртуальные функции и абстрактные классы

виртуальная функция

В C++ виртуальная функция — это функция с префиксом ключевого слова virtual. После переопределения подкласса виртуальная функция может получить доступ к переопределенному методу в своем подклассе через указатель типа своего суперкласса.

Предположим, мы хотим разработать игру,

Есть две роли, маг и фехтовальщик,

И у обоих есть два защищенных атрибута: плавающая кровь и плавающая мана.

Маг будет потреблять 10 очков маны при атаке, а мечник не будет потреблять очки маны при атаке;

При ранении мага он получит полный урон.При ранении мечника, потому что собственная броня мечника может защитить от 20% урона.

У мага 100 атак, у мечника 80 атак, у обоих по 100 здоровья и маны.

Таким образом, наш код можно записать так:

Выходной результат:

Если мы удалим ключевое слово virtual в приведенном выше коде, вывод станет следующим:

Видно, что здесь указатель родительского класса Character* c обращается только к методу getHurt() в родительском классе для получения урона, поэтому мечник был вычтен из 100 крови и не получил урона согласно нашей переписанной функции getHurt(), но после того, как мы добавим ключевое слово virtual в метод getHurt() родительского класса, указатель родительского класса Character* c может получить доступ к переписанному методу getHurt() подкласса, так что фехтовальщик может уменьшить урон на 20%.

чисто виртуальная функция

Если вы добавите =0 в конце виртуальной функции, то она станет чистой виртуальной функцией.

Чисто виртуальные функции имеют следующие характеристики:

(1) Чисто виртуальная функция не имеет тела функции;

(2) «=0» в конце не означает, что возвращаемое значение функции равно 0, оно играет лишь формальную роль, сообщая системе компиляции, что «это виртуальная функция»;

(3) Это оператор объявления с точкой с запятой в конце.

(4) Класс хотя бы с одной чистой виртуальной функцией называется абстрактным классом.Сам абстрактный класс не может быть создан непосредственно, но его подклассы могут быть созданы после перезаписи метода чистой виртуальной функции в родительском классе.

абстрактный класс

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

Поэтому C++ предоставляет нам функцию абстрактного класса (также известную как интерфейсный класс), так что мы можем специально написать такой интерфейсный класс.

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

После переопределения чистой виртуальной функции в производном классе производный класс может создать экземпляр объекта.

Тогда на C++ мы можем написать:

Выходной результат:

переопределить ключевое слово

Ключевое слово override — это синтаксический сахар, добавленный в стандарт C++11, чтобы помочь вам переопределить виртуальные функции в родительском классе.

При отсутствии ключевого слова override, если параметры, имена и атрибуты метода, который вы переписываете, отличаются от параметров, имен и атрибутов метода родительского класса, компилятор не сообщит об ошибке, а будет рассматривать его как новую функцию, и программа нарушит ваши пожелания следующим образом:

Если вы хотите убедиться, что вы правильно переписали метод в родительском классе, вы можете добавить ключевое слово override после метода, который вы переписываете, и компилятор проверит таблицу формальных параметров, тип и атрибут написанного вами переписанного метода. это то же самое, что и метод родительского класса, если он отличается, будет сообщено об ошибке, чтобы напомнить вам исправить это

Если вы хотите переопределить чисто виртуальную функцию, то после ключевого слова переопределения следует добавить = 0, как показано ниже:

конечное ключевое слово

Ключевое слово final также является новым синтаксическим сахаром в C++11, помогающим предотвратить переопределение метода родительского класса, а также может предотвратить наследование родительского класса.

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

Если вы пишете ключевое слово final после имени родительского класса, то родительский класс не может быть унаследован, как показано ниже:

статический

статическая переменная-член

В C++ память объекта включает в себя его переменные-члены.Разные объекты занимают разные области памяти, что делает переменные-члены разных объектов независимыми друг от друга, а их значения не зависят от других объектов. Например, есть два объекта a и b одного типа, оба из которых имеют переменную-член name_, тогда изменение значения a.name_ не повлияет на значение b.name_.

Но когда мы на самом деле программируем, иногда мы хотим, чтобы у объекта определенного типа были некоторые общие данные, вместо того, чтобы хранить копию данных для каждого экземпляра объекта.

Таким образом, в C++ статические переменные-члены предоставляются для достижения цели совместного использования данных между несколькими объектами. Статическая переменная-член — это специальная переменная-член, которая изменяется с помощью ключевого слова static, например:

Выходной результат:

Статические переменные-члены являются общими для всех объектов этого класса и не принадлежат конкретному объекту.Даже если создается несколько объектов, выделяется только одна копия памяти.После создания первого экземпляра этого класса статические переменные-члены Хранится в пространстве памяти Место в фиксировано или статически неизменно (то есть статическое хранилище), и все экземпляры этого класса будут использовать данные в этой памяти.

Таким образом, в приведенном выше коде после изменения статической переменной-члена a[1].b=5 значение a[2].b также будет равно 5, поскольку все они используют одну и ту же область памяти.

Статические методы (также известные как статические функции-члены)

Если вы объявляете член функции как статический, вы можете изолировать функцию от любого конкретного объекта класса.

Статические функции-члены можно вызывать, даже если объект класса не существует. Доступ к статическим функциям можно получить , используя имя класса и оператор разрешения области видимости :: .

Статические функции-члены могут обращаться только к статическим данным-членам, другим статическим функциям-членам и другим функциям вне класса.

Статические функции-члены имеют область действия класса, они не могут получить доступ к указателю this класса. Вы можете использовать статические функции-члены, чтобы узнать, были ли созданы определенные объекты класса.

Например:

Выходной результат:

추천

출처blog.csdn.net/lifesize/article/details/128582539