sinf Hayvon {
ommaviy :
void / * virtual bo'lmagan * / move () {
std :: cout << "Bu hayvon biroz harakat qiladi" << std :: endl ;
}
virtual void eat () {
std :: cout << "Hayvon nimadir yeydi!" << std :: endl ;
}
virtual ~ Animal () {} // halokatchi
};
sinf Kurt : ommaviy hayvon {
ommaviy :
void move () {
std :: cout << "Kurt yuradi" << std :: endl ;
}
void ovqat ( void ) { // ovqat usuli qayta belgilanadi va shuningdek virtualdir
std :: cout << "Olma go'shtni eydi!" << std :: endl ;
}
};
int main () {
Hayvonlar * hayvonot bog'i [ ] = { yangi Wolf (), yangi hayvon ());
uchun ( Hayvon * a : hayvonot bog'i) {
a -> move ();
a -> eat ();
o'chirish ; // Yo'qoluvchi virtual, har biri uchun
// ob'ekt sinfi yiqituvchisini chaqiradi
}
qaytish 0 ;
}
Xulosa :
Bu hayvon biroz harakat qiladi
Qul go'shtni eydi!
Bu hayvon biroz harakat qiladi
Hayvon ovqatlaning bir narsa !
PHP da virtual funktsiyalar analoglari misoli [ tahrir | tahrirlash kodi ]
PHP ga o'xshashki, kechiktirilgan statik ulanishdan foydalanishdir. [ 1]
sinf Foo {
ommaviy statik funktsiyasi baz () {
qaytish " suv " ;
}
ommaviy funktsiyasi __construct () {
echo static :: baz (); // kechroq statik ulanish
}
}
sinf Bar uzaytiradi Foo {
ommaviy statik funktsiyasi baz () {
qaytish " olov " ;
}
}
yangi Foo (); // ezilgan "suv"
yangi Bar (); // "olovni" keltiradi
Delphi- da virtual funktsiyaning misoli [ tahrir | tahrirlash kodi ]
polimorfizm tili Ob'ekt Paskal , Delphida ishlatilgan . Ko'raylik misol :
E'lon qiling ikkita sinf . Ancestor (Ancestor):
TAncestor = sinf
xususiy
himoyalangan
ommaviy
{ Virtual amaliyoti .}
amaliyoti VirtualProcedure ; virtual;
amaliyoti StaticProcedure ;
tugatish ;
va uning avlod ( avlod ):
TDescendant = sinf ( TAncestor )
xususiy
himoyalangan
ommaviy
{ Yopish virtual tartib-qoidalar .
amaliyoti VirtualProcedure ; bekor qilish;
amaliyoti StaticProcedure ;
tugatish ;
As paydo bo'ladi ichida sinfda ajdodlari e'lon qildi virtual funktsiyasi - VirtualProcedure . Polimorfizmdan foydalanish uchun bu kerak blokirovka qilish avlodda.
Dastur quyidagi kabi ko'rinadi:
{ TAncestor }
amaliyoti TAncestor.StaticProcedure ;
boshlang
ShowMessage ( "Ancestor static procedure");
tugatish ;
amaliyoti TAncestor.VirtualProcedure ;
boshlang
ShowMessage ( "Dastlabki virtual amaliyot.");
tugatish ;
{ TDescendant }
amaliyoti TDescendant.StaticProcedure ;
boshlang
ShowMessage ( " Ajratilgan statik protsedura.");
tugatish ;
amaliyoti TDescendant.VirtualProcedure ;
boshlang
ShowMessage ( " Dekanni bekor qilish amaliyoti.");
tugatish ;
Keling, qanday ishlashini ko'rib chiqamiz:
tartibi TForm2.BitBtn1Click (jo: TObject);
bor
MyObject1: TAndcestor ;
MyObject2: TAndcestor ;
boshlang
MyObject1 : = TAncestor .Qiziqarli;
MyObject2 : = TDescendant .Qiziqarli;
harakat qilib ko'ring
MyObject1.StaticProcedure;
MyObject1.VirtualProcedure;
MyObject2.StaticProcedure;
MyObject2.VirtualProcedure;
oxirida
MyObject1.Free;
MyObject2.Free;
tugatish ;
tugatish ;
Ahamiyat bering ichida bo'limiga qarang bor bizmiz e'lon qildi ikkita ob'ekt Myobject1 va Myobject2 kabi Tendan . Va yaratishda Myobject1 sifatida yaratilgan TAncestor va Myobject2 kabi T.Descendant . Bu tugma bosilganda biz nimani ko'ramiz. BitBtn1 :
Otasi statik amaliyoti .
Otasi virtual amaliyoti .
Otasi statik amaliyoti .
Tug'ilishdan bekor qilish amaliyoti .
Uchun Myobject1 har bir narsa aniq, belgilangan protsedura oddiygina sabab bo'ldi. Lekin uchun Myobject2 bu unday emas.
Qo'ng'iroq qiling MyObject2.StaticProcedure; " Ancestor " ning paydo bo'lishiga olib keldi statik amaliyoti . " Axir, biz e'lon qildik MyObject2: TAndastor , shuning uchun protsedura chaqirildi StaticProcedure ; sinf Tendan .
Biroq, bu muammo MyObject2.VirtualProcedure; qiyinchiliklarga olib keldi VirtualProcedure ; ( TDescendant ) bolaga tatbiq etiladi . Bu sabab bo'ldi Myobject2 sifatida yaratilmagan Tarkan , lekin qanday qilib TDescendant : MyObject 2 : = TDescendant.Create ; . Va virtual metodlar Virtual jarayon bloklandi.
Delphi polimorfizm bir deb atalmish tomonidan amalga oshiriladi virtual uslub jadvali (yoki VMT).
Ko'pincha virtual metodlarlar unutiladi. blokirovka qilish kalit so'zdan foydalanish bekor qilish . Bunga sabab bo'ladi yopish usuli. Bunday holda, VMT da usullarni almashtirish amalga oshmaydi va kerakli funksionallik olinmaydi.
Ushbu xato kompilyator tomonidan kuzatiladi, bu esa tegishli ogohlantirishni beradi.
C # O'RNAK virtual metodlari [ chaqirish | tahrirlash kodi ]
C # da virtual metodlarga misol. Misol kalit so'zdan foydalanadi uslubga kirishni ta'minlaydigan bazani tashkil etadi a ( ) ota-ona (asosiy) sinf A.
sinf Dastur
{
statik void Asosiy ( string [] args )
{
A myObj = yangi B ( );
Console.ReadKey ( );
}
}
// asosiy sinf A
ommaviy sinf A
{
ommaviy virtual string a ()
{
qaytish " olov " ;
}
}
// o'zboshimchalikli B klassi
sinf B : A
{
ommaviy bekor qilish string a ()
{
qaytish "suv" ;
}
ommaviy B ()
{
// Bekor qilish usuli bilan qaytarilgan natijani ko'rsatish
Console.Out.WriteLine (a ()); // suv
// Ota-guruh usulida qaytarilgan natijani ko'rsatish
Console.Out.WriteLine ( tayanch .a ()); // olov
}
}
Bir-biriga biriktirilgan usuldan ajdod uslubini chaqirish [ tahrir | tahrirlash kodi ]
Nomli usulda ajdod uslubini chaqirish kerak bo'lishi mumkin.
Ikkita sinfni e'lon qiling. Ancestor ( Ancestor ):
TAncestor = sinf
xususiy
himoyalangan
ommaviy
{ Virtual amaliyoti .}
amaliyoti VirtualProcedure ; virtual;
tugatish ;
va uning avlod ( avlod ):
TDescendant = sinf ( TAncestor )
xususiy
himoyalangan
ommaviy
{ Yopish virtual tartib-qoidalar .
amaliyoti VirtualProcedure ; bekor qilish;
tugatish ;
Ajdod uslubiga qilingan chaqiruv " meros qilib olingan " kalit so'zidan foydalanib,
amaliyoti TDescendant.VirtualProcedure ;
boshlang
meros qilib olingan ;
tugatish ;
Delphi halokat, albatta ketma-ket kerak, deb eslab arziydi - " bekor " - va ajdodlarining halokatli chaqiruvi mavjud
TDescendant = sinf ( TAncestor )
xususiy
himoyalangan
ommaviy
destructor Destroy; bekor qilish;
tugatish ;
halokat T.Descendant . Yo'q qiling ;
boshlang
meros qilib olingan ;
tugatish ;
C ++ da siz ajdodning konstruktori va halokatiga qo'ng'iroq qilishingiz shart emas, halokat virtual bo'lishi kerak. Otadan ajraluvchilar avtomatik ravishda chaqiriladi. Otadan usulini izlash uchun quyidagi usulni aniq chaqirishingiz kerak:
sinf Otasi
{
ommaviy :
virtual void function1 () { printf ( "Ancestor :: function1" ); }
};
sinf Tug'ilishdan : jamoat ajdodi
{
ommaviy :
virtual void function1 () {
printf ( "Descendant :: function1" );
Ancestor :: function1 ( ); // bu erda bo'ladi bosilgan "Ancestor :: function1"
}
};
Agar ajdodning konstruktoriga qo'ng'iroq qilish uchun siz konstruktorni ko'rsatishingiz kerak:
sinf Tug'ilishdan : jamoat ajdodi
{
ommaviy :
Descendant ( ) : Ancestor () {}
};
Boshqa misollar
Birinchisi bir misol
sinf Otasi
{
ommaviy :
virtual void function1 () { cout << "Ancestor :: function1 ()" << endl ; }
void function2 () { cout << "Ancestor :: function2 ()" << endl ; }
};
sinf Tug'ilishdan : jamoat ajdodi
{
ommaviy :
virtual void function1 () { cout << "Descendant :: function1 ()" << endl ; }
void function2 () { cout << "Descendant :: function2 ()" << endl ; }
};
Descendant * pointer = yangi Descendant ();
Ancestor * Pointer_copy = ko'rsatgich;
pointer -> function1 ();
pointer -> function2 ();
pointer_copy -> function1 ();
pointer _copy -> function2 ();
Ushbu misolda sinf Otasi ikkita funktsiyani belgilaydi, ulardan biri virtual, ikkinchisi esa virtual - Yo'q. Sinf Tug'ilishdan ikkala vazifani bekor qiladi. Shu bilan birga, funktsiyalarga bir xil kirish turli natijalar beradi. Yoqilgan xulosa dastur beradi quyidagilar :
Descendant :: function1 ()
Descendant :: function2 ()
Descendant :: function1 ()
Ancestor :: function2 ()
Ya'ni, virtual funktsiyani amalga oshirishni aniqlash uchun ob'ekt turiga oid ma'lumotlar ishlatiladi va ko'rsatgich turidan qat'i nazar, "to'g'ri" dastur amalga oshiriladi. Virtual bo'lmagan funksiyani chaqirganda , derleyici ko'rsatgich turi yoki mos yozuvlar turi bo'yicha boshqariladi, shuning uchun ikkita turli xil ilovalar chaqiriladi function2 () , bir xil ob'ekt ishlatilgan bo'lsa-da.
Shuni ta'kidlash joizki, C ++ da agar zarurat bo'lsa, virtual bo'lmagan funktsiyani amalga oshirishni aniq belgilashingiz mumkin, aslida u virtual emas :
Pointer -> Otasi :: function1 ();
Bizning misol ko'rsataman uchun Ajdod :: function1 (), ob'ekt turiga e'tibor bermayapti.
Ikkinchidan bir misol
sinf A
{
ommaviy :
virtual int funktsiyasi () {
qaytish 1 ;
}
int get () {
qaytish Bu -> funktsiya ();
}
};
sinf B : ijtimoiy A
{
ommaviy :
int funktsiyasi () {
qaytish 2 ;
}
};
#include < iostream >
int main () {
B b;
std :: cout << b.get ( ) << std :: endl ; // 2
qaytish 0 ;
}
Sinfda bo'lishiga qaramay B etishmayotgan usul get ( ) funktsiyasidan foydalansa, u sinfdan qarz olishi mumkin A , ushbu uslubning natijasi hisobni qaytaradi B :: function () !
Uchinchidan bir misol
#include < iostream >
foydalanish nom maydoni std ;
struct IBase
{
virtual void foo ( int n = 1 ) konst = 0 ;
virtual ~ IBase () = 0 ;
};
void IBase :: foo ( int n) const {
cout << n << "foo \ n " ;
}
IBase :: ~ iBase () {
cout << "Base destructor \ n " ;
}
struct Derived finali : IBase
{
virtual void foo ( int n = 2 ) konst bekor qilish final {
IBase :: foo ( n);
}
};
void bar ( const IBase & arg )
{
arg.foo ( );
}
int main () {
bar ( Derived ());
qaytish 0 ;
}
Ushbu misol, IBase interfeysini yaratishning namunasini ko'rsatadi . Interfeysning namunasi virtual metodlarlari bo'lmagan mavhum bir sinf yaratish imkoniyatini ko'rsatadi: virtual halokatli virtualni e'lon qilganda va uning tanasini sinf tanasining orqasida belgilashda, ushbu sinfning ob'ektlarini yaratish qobiliyati yo'qoladi, ammo bu ajdodning avlodlarini yaratish mumkin.
Dasturning chiqishi quyidagicha bo'ladi: 1 foo \ nBaza destructor \ n. Ko'rib turganimizdek , standart argument qiymati ob'ektning haqiqiy turidan emas, balki aloqa turidan keladi. Yomonlik bilan bir qatorda.
Yakuniy kalit so'z bir usul yoki uslubni qayta aniqlash mumkin emasligini va virtual metodlar aniq aniqlanganligini bekor qilishini ko'rsatadi.
Do'stlaringiz bilan baham: |