ПредишенСледващото

Виртуалните функции. Какво е това? част 1

Част 1: Обща теория на виртуални функции

С поглед към заглавието на тази статия, може да мислите: "Хм, които не знаят какво е виртуална функция е същото!". Ако е така, сигурно можете да се откажат от четене на самия сайт.

А за тези, които тепърва започват да разбират тънкостите на C ++, но вече има, например, основни познания за такива неща като наследство. и аз чух нещо за полиморфизъм. Той има пряк смисъл да прочетете този материал. Ако разбирате виртуални функции, вие ще получите представа за тайните на успешния обектно-ориентиран дизайн.

Всички материали, реших да се раздели на 3 части.
Нека се опитаме да разберем в първата част в общата теория на виртуални функции. Нека да видим във втората част на тяхното прилагане (и своята сила и власт!) В един повече или по-малко от реалния живот, например. Е, и третата част ще говорим за такива неща като виртуални деструктори.

И така, какво е това?

Нека първо си припомним как в класическата програмиране в C, можете да мине информационния обект на функцията. Нищо сложно за него, само трябва да се уточни вида на обекта, преминали по това време, когато пишете функция код. Това е, за да опише поведението на обекти, е необходимо предварително да се знае и да се опише техния вид. Силата на ООП в този случай се проявява в това, че можете да напишете виртуални функции, така че самия обект определя какво да функционира, е необходимо да се обадите по време на програмата.

С други думи - с помощта на виртуална функция обект определя себе си поведение (собствени действия). Техниката на използване на виртуални функции просто наричат ​​полиморфизъм. Полиморфизъм буквално означава като много форми. Обект в програмата може в действителност да представлява повече от един клас, а броят на различни класове, ако те са свързани механизъм наследство от общ базов клас. Е, на поведението на обектите на тези класове в йерархията, разбира се, ще бъде различно.

Е, сега, за да бизнес!

Както е известно, в съответствие с правилата на C ++ указател към базовия клас може позоваване обект на този клас, както и всеки друг обект клас, получен от основата. Разбирането на това правило е много важно. Нека да разгледаме някои прости йерархия от класове А, Б и В. И ние ще имаме база клас Б - се показва (генерира) от класа, и C - получена от Б. Обяснения виж по-долу.

програмни обекти на тези класове могат да се декларират, например, по такъв начин.


Според този тип правило А показалеца може да се отнася към някоя от тези три обекта. Това е, така че ще бъде вярно:


Но това не е прав:


Въпреки факта, че point_to_Object показалеца е от тип A *, не C * (или C *), тя може да се отнася за обекти от тип С (или В). Тя може да бъде обикновено е по-лесно да се разбере, ако мислите, че за обект C, като специална форма на А. Ами, например, един пингвин - специален вид птица, но то все още остава една птица, но не лети. Разбира се, връзката на обекти и указатели работи само в една посока. Един обект от тип C - специален вид обект А, но не е обект е специален вид на обекта С, с пингвини, можете спокойно да се каже, че ако всички птици са специален вид пингвини - те просто няма да знаят как да летят!

клас А
публичния:
виртуална невалидни v_function (свободен); // функция описва поведението на определен клас
>;


Виртуална функция може да се декларира с параметри, той може да върне стойност, както и всяка друга функция. Класът може да бъде обявен за виртуални функции, колкото е необходимо. И те са в някаква част от този клас - затворен, отворете или защитени.

Ако една от клас B, генерирани от този клас трябва да бъдат описани кока нещо по-различно поведение, може да декларира виртуална функция, наречена отново v_function ().

клас Б: обществен A
публичния:
виртуална невалидни v_function (свободен); // заместване функция описва някои
// нов клас поведение
>;


Когато в класната стая, като Б, определя виртуална функция, която е със същото име с родоначалник клас виртуална функция, тази функция се нарича смяна. Виртуална функция v_function () замества във виртуалната функция със същото име в клас А. Всъщност, всичко е по-сложно и не може да се свежда до обикновено съвпадение на имена. Но повече за това по-късно, в раздел "Някои приложения на тънкостите."
Е, сега най-важното нещо!

Да се ​​върнем към индекс point_to_Object типа A *, който се отнася до object_V обект от тип B *. Нека да разгледаме по-подробно изявление, в което се призовава функцията за виртуален v_function () на обекта, посочи point_to_Object.

Е, това, което правим за вас?

Това е време да погледнем - и това, което ни е дадено виртуални функции? От теорията на виртуални функции като цяло имахме един поглед. Време е да се помисли за някаква реална ситуация, където е възможно да се разбере практическата стойност на обекта в реалния свят на програмиране.

Класически пример (в моя опит - 90% от литературата на C ++), което доведе до тази цел - за написването на графична програма. Конструиран клас йерархия, нещо като "-gt точка; -gt линия, равнина фигура -gt; обем фигура". И помисли за виртуална функция, да кажем, Draw (), което го прави всичко. Boring!

Нека да разгледаме по-малко академично, но въпреки графичен пример. (Classic! Къде отиде от него?). Нека разгледаме един хипотетичен принцип, който може да се включи в компютърна игра. И не само в играта, както и на базата на който и да е (без значение 3D или 2D, стръмен или горе-долу) стрелецът. Стрелба, просто казано. Аз не съм кръвожаден живот, но грешник, като понякога някои стрелба!

Така че, ние планира да направи остър стрелецът. Какво е необходимо на първо място? Разбира се, оръжието! (Е, може би не в първата. Той не е от значение.) В зависимост от това, което темата ще състави подобни оръжия и нужда. Може би това ще бъде набор от клубове от прост до арбалет. Може би от аркебуза да граната. И може би всички от силен вятър на разпадащото. Скоро ще видите, че това е нещо, просто не е от значение.

Е, пак има много възможности, е необходимо да има базов клас.

клас оръжие
публичния:
. // тук са членове на данни, които могат да бъдат описани, например,
// дебелината на клубовете, а броят на гранати в граната
// това не е важно за нас

виртуален невалидни употреба1 (недействителни); // обикновено - левия бутон на мишката
виртуален невалидни употреба2 (недействителни); // обикновено - десен бутон на мишката

// все още има някои от членовете на данни и методи
>;


Без да навлизаме в подробности за този клас, можем да кажем, че най-важното, може би, ще употреба1 () функцията и употреба2 (), който описва поведението (или приложението) на тези оръжия. От този клас може да произвежда всички видове оръжия. Ще се добавят нови членове на данни (като например броя на кръговете, курс, ниво на мощност, дължината на лопатките и т.н.) и новите функции. И по-висш употреба1 () и употреба2 (), ще опишем разликите в използването на оръжие (нож тя може да бъде ударен и хвърляне на машина - стрелба единични и опашки).

Колекция от оръжия трябва да се съхраняват някъде. Може би най-лесният начин да се организира този тип масив Оръжейни * указатели. За простота се предположи, че това е глобален набор от оръжия е, 10 вида оръжия, както и всички насоки, за да започнете да инициализира на нула.

Оръжие * оръжие [10]; // масив от указатели към обекти от тип оръжие


Създаване в началото на програмата на динамични обекти, оръжия, ние ще ги добавите като указатели към масива.

За да се уточни какво оръжие са в употреба, ръководителят на променлива индекс на масив, чиято стойност ще се промени в зависимост от вида на оръжието.


В резултат на тези усилия, код, който описва използването на оръжия в играта може да изглежда така:

ако (LeftMouseClick) оръжие [TypeOfWeapon] -gt; употреба1 ();
друго оръжие [TypeOfWeapon] -> употреба2 ();


Всичко! Създали сме код, който описва стрелба изгаряне-войната още преди да реши кои видове оръжия, за да бъдат използвани. Освен това. Ние обикновено не разполагат с никакви недвижими вид оръжия! General (понякога много важно) и ползите - Този код може да се компилира отделно и се съхраняват в библиотеката. В бъдеще, вие (или друг програмист) може да донесе нови класове на оръжие, да ги запазвате в масив на оръжие # 91] и употреба. Не е нужно да компилирате кода си.

Особено внимание, че този код не изисква от вас да се уточни точно кои видове обекти с данни, които са цитирани от указатели Arms # 91], като изисква само, че те са били получени от оръжието. Обекти определят по време на изпълнение. какво функция условия (), те трябва да се обадите.

Някои приложения на тънкостите на

Нека да отнеме малко повече време, дадено на проблема със заместването на виртуални функции.

Обратно към началото - към скучния класове A, B и C. клас C в момента ние трябва най-долу в йерархията, в края на линията на наследяване. В един клас с един и същи начин можете да определите подмяна виртуална функция. И за да използвате виртуалната ключова дума не е задължително, защото това е последната класа в линията на наследяване. Функция и така ще работи и да бъде избрана като виртуална. Но! Но ако не се чувствате желание да донесе клас D на клас С, и дори да променят v_function на поведение () функция, тогава има само нищо не се случва. За да направите това във функцията клас v_function () трябва да се декларира като виртуална. Оттук и правилото, че може да се формулира по следния начин: "след като виртуален - виртуалното винаги!". Това означава, че виртуалната Ключовата дума е най-добре да не се изхвърля - изведнъж дойде по-удобно?

Друг финес. Извлечения клас не може да се определи функция със същото име и с един и същ набор от параметри, но с различен тип възвръщаемост от тази на виртуална функция на базовия клас. В този случай, компилаторът се закле по време на компилация на програмата.

Напред. Ако получени клас да се въведе функцията на едно и също име и да се върнете тип като базов клас виртуална функция, но с различен набор от параметри, а след получен функцията клас няма да бъде виртуален. Дори и да ви придружи я виртуална ключова дума, че няма да е това, което сте очаквали. В този случай, с помощта на курсора в базовия клас за всяка стойност на тази показалка ще получите достъп до базов клас. Не забравяйте правилото за претоварване! Това е просто една различна функция. Вие ще имате съвсем различен виртуална функция. Като цяло тези грешки много неуловим, тъй като и двете форми на навлизане на пазара са доста приемливи и се надяват за диагностика на компилатора в този случай не е необходимо.

Следователно друго правило. Чрез заместване на виртуални функции изисква пълно съвпадение на вида на параметрите, имена на функции и видове стойности за връщане в базата и извлечения клас.

И още един. Виртуална функция може да бъде само нестатичен компонент функция на класа. Виртуален не може да бъде глобална функция. Виртуална функция може да бъде обявена за приятелски (

) В друг клас. Но в приятелски функции ще обсъдим как и дали в друга статия.

Това е всичко за това време.

В следващата част ще видите напълно функционален пример за една проста програма, която показва всички точки, които обсъдихме.

В това писание, следното книги:

Ако имате някакви въпроси - пишете, ще проучим.

Сергей Malyshev (известен още като Михалич).

Свързани статии

Подкрепете проекта - споделете линка, благодаря!