Файл: Виртуалды дістер.doc

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 12.04.2024

Просмотров: 8

Скачиваний: 0

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.



Виртуалды əдістер


Объектілермен жұмыс көбінесе нұсқауыштар арқылы орындалады. Базалық класс нұсқауышына кез келген туынды кластың объектісі адресінің мəнін меншіктеуге болады (ашық мұралау кезінде):





1Туынды класта тек виртуалды əдістерді қайта анықтаған жөн (келесі бөлімді қараңыз).

// Базалық класқа нұсқауыш сипатталады:

monstr *p;

// Нұсқауыш туынды класс объектісіне сілтеме жасайды: р = new daemon;

Объектінің əдістерін шақыру нұсқауыш сілтеме жасайтын объектінің нақты типіне емес, нұсқауыштың типіне сəйкес орындалады, сондықтан опе- ратор орындалғанда, мысалы,

p->draw(l, 1, 1, 1);

операторының орындалуы кезінде daemon класының емес, monstr класының əдісі шақырылады, өйткені əдістерге сілтемелер программаны жинақтау ба- рысында рұқсат етіледі. Бұл үрдіс ерте байланыстыру деп аталады. daemon класының əдісін шақыру үшін нұсқауыш типін тікелей түрде түрлендіруді қолдануға болады:

((daemon * p))->draw(1, 1, 1, 1);

Бұл əрқашан мүмкін бола бермейді, өйткені əртүрлі уақыт мезетінде нұсқауыш иерархияның əртүрлі кластарының объектілеріне сілтеме жасауы мүмкін жəне программаның компиляциясы кезінде нақты класс белгісіз болуы мүмкін. Мысал ретінде параметрі базалық класс объектісіне нұсқауыш болып табылатын функцияны келтіруге болады. Программаның орындалуы кезінде оның орнына кез келген туынды класқа нұсқауыш берілуі мүмкін. Басқа мы- сал – иерархияның əртүрлі объектілеріне нұсқауыштардың байланысқан тізімі, бұл тізіммен бір сипатта жұмыс істеу керек.

Ерте байланыстырумен қатар, C++ тілінде кейінгібайланыстырумеханизмі жүзеге асырылған, мұнда əдіске сілтемелер жасауға рұқсат беру əдісті шақырған объектінің нақты типіне байланысты программаның атқырылу кезеңінде орындалады. Бұл механизм виртуалды əдістер көмегімен жүзеге асырылған, ол келесі бөлімде қарастырылады.

Виртуалды əдісті анықтау үшін virtual спецификаторы қолданылады, мысалы:

virtual void drawdnt x, int у, int scale, int position);


Виртуалды əдістерді сипаттау жəне пайдалану ережелерін қарастырайық:

  • Егер базалық класта əдіс виртуалды ретінде анықталған болса, туынды класта дəл осындай атаумен жəне параметрлер жиынтығымен анықталған əдіс автоматты түрде виртуалды болады, ал параметрлержиынтығыəртүрлі болса, əдіс қарапайым болады.

  • Виртуалды əдістер мұраланады, яғни оларды туынды класта қайта анықтау тек айырықша əрекеттерді тағайындау қажет болғанда орындалады. Қайта анықтау кезінде оларға қол жеткізу құқықтарын өзгертуге болмайды.

  • Егер виртуалды əдіс туынды класта қайта анықталған болса, осы класс объектілері көріну аймағына қол жеткізу операциясының көмегімен базалық класс əдісін пайдалану мүмкіндігіне ие бола алады.

  • Виртуалды əдісті static модификаторы арқылы жариялауға болмайды, бірақ ол достас əдіс ретінде жариялануы мүмкін.

  • Егер класта виртуалды əдістің сипаттамасы енгізілетін болса, ол ең болмағанда, таза виртуалды əдіс ретінде анықталуы керек.

Таза виртуалды əдісте оның тұлғасының орнына = 0 белгісі жазылады, мысалы:

virtual void f(int) = 0;

Таза виртуалды əдіс туынды класта қайта анықталуы тиіс (қайтадан таза виртуалды əдіс ретінде анықталуы мүмкін).

Егер monstr класындағы draw əдісін виртуалды əдіс ретінде анықтасақ, қай кластың əдісін шақыру қажеттігі туралы шешім нұсқауыш сілтеме жасай- тын объектінің типіне байланысты қабылданатын болады:

monstr *r. *р;

r = new monstr; // monstr класының объектісі құрылады р = new daemon; // daemon класының объектісі құрылады r->draw(l, 1, 1, 1); // monstr::draw əдісі шақырылады

p->draw(l, 1, 1, 1); // daemon::draw əдісі шақырылады

р-> monstr::draw(l, 1, 1, 1); // Виртуалды əдістер

// механизмін қолданбау

Егер daemon класының объектісі draw əдісін тікелей емес, жанама түрде (яғни, monstr класында анықталған басқа əдістен) шақыратын болса, онда daemon класының draw əдісі шақырылады.

Сонымен, программаның орындалу кезеңінде өзіне сілтеме жасауға рұқсат етілетін əдіс виртуалды деп аталады (ағылшынның əдемі virtual сөзінің бұл жердегі аудармасының мағынасы – «нақтылы түрде», яғни шақыру нақты орындалған кезде сілтеме рұқсат
етіледі).

Кейінгі байланыстыру механизмі

Ең кем дегенде бір виртуалды əдісі бар əрбір класс (объект емес!) үшін ком- пилятор виртуалды əдістер кестесін (vtbl) құрады, мұнда əрбір виртуалды əдіс үшін оның компьютер жадындағы адресі жазылады. Кестедегі əдістердің адрестері олардың кластардағы сипатталу реттілігіне сəйкес орналасады. Кез келген виртуалды əдістің адресі иерархия құрамындағы əрбір класс үшін vtbl кестесінде бірдей ығысуға ие болады.

Vtbl кестесіне əрбір объектінің сілтеме жасайтын жасырын қосымша vptr деп аталатын өрісі болады. Ол объект құру кезінде конструктор көмегімен толтырылады (бұл үшін компилятор конструктор тұлғасының бастапқы жағына соған сəйкес нұсқауларды қосады).

Компиляция кезеңінде виртуалды əдістерге жасалған сілтемелер vptr объектісі арқылы vtbl кестесін пайдалану əрекеттеріне алмастырылады, ал программаның орындалуы кезеңінде əдісті пайдалану кезінде оның адресі

кестеден таңдалып алынады. Осылайша, қарапайым əдістер мен функциялар- мен салыстырғанда, виртуалды əдісті шақыру кестеден əдіс адресін алудың қосымша кезеңі арқылы жүзеге асырылады. Бұл программаның орындалуын бірқатар баяулатады.

Динамикалық объектіге бөлінген жадының дұрыс босатылуын қамтамасыз ету үшін, деструкторларды виртуалды етіп құру ұсынылыды, өйткені мұндайда кез келген уақытта объектінің нақты типіне сəйкес келетін деструк- тор таңдалып алынады. Деструктор delete операциясына size_t типіндегі объектінің өлшемін жібереді. Егер өшірілетін объект туынды болса жəне оның құрамында виртуалды деструктор анықталмаса, онда жіберілген объект өлшемі дұрыс болмауы мүмкін.

Əдісті виртуалды жасаудың нақты ережесі жоқ. Туынды класта қайта анықталу ықтималдығы бар əдістерді виртуалды ретінде жариялау туралы ұсыныс қана беруге болады. Барлық иерархия деңгейлерінде өзгеріссіз қалатын немесе туынды кластар қолданбайтын əдістерді виртуалды етудің қажеті жоқ. Басқа жағынан алғанда, иерархияны
жобалау кезінде базалық кластардың қандай жолмен кеңейтілетінін алдын ала болжау əрқашанда мүмкін бола бермейді (əсіресе кластар кітапханаларын жобалағанда), ал əдісті виртуалды ретінде жариялау икемділік пен кеңейту мүмкіндігін қамтамасыз етеді.

Соңғы жағдайды түсіндіру үшін draw əдісін шақыру объектінің орнын ауыстыру əдісінен орындалады деп есептейік. Егер орын ауыстыру əдісінің мəтіні орны ауыстырылатын объект типіне байланысты болмаса (барлық объектілердің орын ауыстыру принциптері бірдей болғандықтан, ал суреттеу үшін нақты əдіс шақырылатындықтан), туынды кластарда бұл əдісті қайта анықтаудың қажеті жоқ жəне оны виртуалды əдіс ретінде сипаттамауға бо- лады. Егер draw əдісі виртуалды болса, орын ауыстыру əдісі қайта компиля- циялаусыз кез келген туынды класс объектілерімен (тіпті оны жазу кезінде белгісіз болған объектілермен де) жұмыс істей алады.

Виртуалды механизм тек объектілерге нұсқауыштарды немесе сілтемелерді қолдану кезінде ғана жұмыс істейді. Нұсқауыш немесе сілтеме арқылы анықталып, виртуалды əдістерді қамтитын объект полиморфты деп атала- ды. Мұндайдағы полиморфизмнің мəні – əдіске бір ғана хабарласу арқылы əрбір уақыт мезетінде нұсқауыш сілтеме жасайтын типке байланысты əртүрлі əрекеттер орындалады.