Java-da polimorfizm. Dinamik və statik bağlama. Obyektlərin işə salınması. Konstruktorlardan çağırıldıqda polimorfik metodların davranışı. Obyekt proqramlaşdırma konstruktorlarına giriş. Ehtiyat sözlər super və bu. Başlanğıc blokları

Optimallaşdırma kimi Statik Bağlantı

Bəzi hallarda, səmərəlilik əsas tələbdir və hətta yuxarıda qeyd olunan kiçik əlavə xərclər də arzuolunmazdır. Bu halda qeyd etmək olar ki, onlar həmişə əsaslandırılmır. Zəng edin x.f (a, b, c...) aşağıdakı hallarda dinamik bağlamaya ehtiyac yoxdur:

1 f sistemin heç bir yerində ləğv edilmir (yalnız bir bəyannamə var);

2 x polimorf deyil, yəni mənbəsi başqa tipdə olan heç bir əlavənin hədəfi deyil.

Bu hallardan hər hansı birində yaxşı bir kompilyator tərəfindən təsbit edilmiş, üçün yaradılmışdır x.f (a, b, c...) kod zəng etmək üçün C, Pascal, Ada və ya Fortran tərtibçiləri tərəfindən yaradılan kodla eyni ola bilər. f (x, a, b, c...). Heç bir əlavə xərc tələb olunmayacaq.

Son mühazirədə təsvir edilən mühitin bir hissəsi olan ISE kompilyatoru hazırda optimallaşdırma (1) həyata keçirir və əlavə etmək planlaşdırılır (2) ((2) təhlili, əslində, tip təhlilinin nəticəsidir. yazıya dair mühazirədə təsvir olunan mexanizmlər).

(1) özlüyündə maraqlı olsa da, onun dərhal faydalılığı dinamik bağlamanın nisbətən aşağı qiyməti ilə məhdudlaşır (yuxarıdakı statistikaya baxın). Ondan real qazanc dolayıdır, çünki (1) üçüncü optimallaşdırmaya imkan verir:

4. Mümkün olduqda istifadə edin prosedur kodunun avtomatik dəyişdirilməsi.

Belə əvəzetmə proqramın gövdəsini çağırılan prosedurun mətni ilə onun çağırıldığı yerdə genişləndirilməsi deməkdir. Məsələn, prosedur üçün

set_a(x:SOME_TYPE) edir

a atributunun yeni dəyərini x edin.

kompilyator zəng etmək üçün yarada bilər s.set_a(bəzi_dəyər) Paskal kompilyatorunun təyinat üçün yaratdığı eyni kod s.a:= bəzi_dəyər(bizim üçün qəbuledilməz bir təyinatdır, çünki bu, məlumatın gizlədilməsini pozur). Bu halda, heç bir əlavə xərc yoxdur, çünki yaradılan kodda prosedur çağırışı yoxdur.

Kodun dəyişdirilməsi ənənəvi olaraq müəyyən edilməli olan optimallaşdırma kimi qəbul edilir proqramçılar. Ada bir praqma daxildir (tərcüməçiyə göstəriş) xətdə, C və C++ oxşar mexanizmləri təklif edir. Ancaq bu yanaşmanın özünəməxsus məhdudiyyətləri var. Kiçik, statik bir proqram üçün səlahiyyətli bir proqramçı hansı prosedurların əvəz oluna biləcəyini müəyyən edə bilsə də, inkişaf edən böyük layihələr üçün bu mümkün deyil. Bu halda, əvəzetmələri təyin etmək üçün layiqli alqoritmi olan kompilyator proqramçıların təxminlərini xeyli üstələyəcəkdir.

Avtomatik statik əlaqənin (1) tətbiq olunduğu hər bir çağırış üçün OO tərtibçisi vaxt-yaddaş nisbətinin təhlili əsasında avtomatik prosedur kodunun dəyişdirilməsinin (3) məqsədəuyğun olub olmadığını müəyyən edə bilər. Bu, ən heyrətamiz optimallaşdırmalardan biridir - əldə istehsal olunan C və ya Fortran kodunun səmərəliliyinin əldə edilməsinin, bəzən isə böyük sistemlərdə üstələnməsinin səbəblərindən biridir.

Proqramın ölçüsü və mürəkkəbliyi ilə artan effektivliyə, kodun avtomatik dəyişdirilməsi daha çox etibarlılıq və çeviklik faydasını əlavə edir. Qeyd edildiyi kimi, kodun dəyişdirilməsi yalnız (1) və (2) hallarda olduğu kimi statik olaraq məhdudlaşdırıla bilən prosedur üçün semantik cəhətdən düzgündür. Bu, nəinki məqbuldur, həm də OO metoduna, xüsusən Açıq-Qapalı prinsipinə uyğundur, əgər bir tərtibatçı böyük bir sistemin inkişafının yarısında, o anda yalnız bir komponentə sahib olan bəzi komponentin ləğvini əlavə edərsə. həyata keçirilməsi. Prosedur kodu əl ilə daxil edilərsə, nəticə səhv semantikaya malik proqram ola bilər (çünki bu halda dinamik əlaqə tələb olunur və kodun daxil edilməsi, əlbəttə ki, statik əlaqə deməkdir). Tərtibatçılar əl ilə edildikdə səhvlərə səbəb olan, lakin əslində avtomatlaşdırıla bilən yorucu optimallaşdırmalara deyil, düzgün proqramların qurulmasına diqqət yetirməlidirlər.

Səmərəlilik haqqında son bir qeyd. Obyekt yönümlü dillər üçün dərc edilmiş statistika göstərir ki, zənglərin 30%-60%-i həqiqətən dinamik bağlamadan istifadə edir. Bu, tərtibatçıların metodların xüsusi xüsusiyyətlərindən necə intensiv istifadə etməsindən asılıdır. İMKB sistemində bu nisbət 60%-ə yaxındır. Yuxarıda təsvir olunan optimallaşdırmalarla siz yalnız həqiqətən ehtiyacı olan zəngləri dinamik şəkildə əlaqələndirmək üçün ödəniş edirsiniz. Qalan dinamik zənglər üçün yerüstü xərclər nəinki kiçikdir (sabitlə məhdudlaşır), həm də məntiqi olaraq zəruridir - əksər hallarda dinamik bağlamaya ekvivalent nəticə əldə etmək üçün şərti ifadələrdən istifadə etməli olacaqsınız ( əgər... onda... və ya halda ... ...), yuxarıdakı sadə massiv əsaslı mexanizmdən daha bahalı ola bilər. Beləliklə, yaxşı bir kompilyatorla tərtib edilmiş OO proqramlarının əl ilə yazılmış C kodu ilə rəqabət apara bilməsi təəccüblü deyil.

Veb saytınızı gücləndirin kitabından müəllif Nikolay Matsievski

Statik arxivləşdirmə fəaliyyətdədir Konfiqurasiya faylında bir neçə sətirlə (httpd.conf və ya .htaccess, birinciyə üstünlük verilir), əgər siz bir neçə dəqiqə sərf etsəniz və bütün lazımi faylları özünüz arxivləşdirsəniz, öhdəsindən gəlməyin bir yolu var. Tutaq ki, bizdə var

The C++ Reference Guide kitabından müəllif Stroustrap Bjarne

R.3.3 Proqram və Əlaqələndirmə Proqram bir-biri ilə əlaqəli bir və ya bir neçə fayldan ibarətdir (§R.2). Fayl təsvirlər ardıcıllığından ibarətdir. Açıqca statik elan edilən fayl əhatəli adı tərcümə vahidi üçün lokaldır və edə bilər

The C# 2005 Programming Language and the .NET 2.0 Platform kitabından. Troelsen Andrew tərəfindən

Dinamik Bağlama Sadə dillə desək, dinamik bağlama və ya dinamik bağlama, müəyyən bir növün nümunələrini yarada və onların üzvlərini iş vaxtında və tərtib zamanı tip haqqında hələ heç nə məlum olmayan şəraitdə çağıra biləcəyiniz bir yanaşmadır.

ArchiCAD 11 kitabından müəllif Dneprov Alexander G

Baxışların əlaqələndirilməsi ArchiCAD-in vizuallaşdırma alətləri arasında məqsədi eyni vaxtda iki fərqli görünüşü birlikdə göstərmək olan bir mexanizm var. Bunun nə mənası var ki, buna ehtiyac tez-tez yaranır. Məsələn, obyektləri vizual olaraq əlaqələndirmək

Obyekt yönümlü proqramlaşdırmanın əsasları kitabından Meyer Bertrand tərəfindən

Dinamik Bağlama Son iki mexanizmin, üstünlüyü və polimorfizmin birləşməsi birbaşa aşağıdakı mexanizmi nəzərdə tutur. Tutaq ki, hədəfi polimorf varlıq olan bir çağırış var, məsələn, BOAT tipli bir obyekt növbə komponentini çağırır.

Windows Mühitində Sistem Proqramlaşdırması kitabından tərəfindən Hart Johnson M

ADT A sinfi ilə əlaqə, dəfələrlə deyildiyi kimi, rəsmi və ya dolayı şəkildə müəyyən edilmiş ADT-nin həyata keçirilməsidir. Mühazirənin əvvəlində qeyd edildi ki, ifadələr sinfə daxil olan semantik xüsusiyyətlərin bir yolu kimi qəbul edilə bilər.

Kitabdan TCP/IP Architecture, Protocols, Implementation (o cümlədən IP version 6 və IP Security) tərəfindən Faith Sydney M

Dinamik Bağlama Dinamik bağlama əsas tetralogiya yaradaraq, üstələmə, polimorfizm və statik yazmağı tamamlayacaq.

Dummies üçün VBA kitabından Steve Cummings tərəfindən

Fərqli Adlı Düymə: Statik Bağlantı Səhv Olduğunda İndiyə qədər bu mühazirədə göstərilən irsiyyət prinsiplərindən əsas çıxış aydın olmalıdır: Dinamik bağlama prinsipi Statik əlaqənin nəticəsi nəticə ilə uyğun gəlmədikdə

UNIX Əməliyyat Sistemi kitabından müəllif Robaçevski Andrey M.

Yazma və Cildləmə Baxmayaraq ki, bu kitabın oxucusu kimi siz statik yazma ilə statik bağlama arasında fərqi ayıra bilsəniz də, bunu edə bilməyən insanlar var. Bu, qismən hər iki problemə dinamik yanaşmanı müdafiə edən Smalltalk-ın təsiri ilə bağlı ola bilər

Başlayanlar üçün C++ kitabından Lippman Stanley tərəfindən

Gizli əlaqələndirmə Gizli əlaqə və ya yükləmə zamanı əlaqə, iki əlaqələndirmə texnikasından daha sadədir. Microsoft C++-dan istifadə proseduru aşağıdakı kimidir: 1. Yeni DLL üçün lazım olan bütün funksiyalar toplandıqdan sonra,

Linux Kernel Development kitabından Love Robert tərəfindən

Açıq Bağlantı Açıq keçid və ya iş vaxtı əlaqələndirilməsi proqramdan DLL-nin nə vaxt yüklənəcəyi və ya boşaldılması barədə xüsusi təlimatlar verməsini tələb edir. Sonra proqram tələb olunan ünvana daxil olur

Müəllifin kitabından

11.9.3 Bağlama DHCP serveri müştərilər və onların konfiqurasiya parametrləri arasında xəritələr cədvəlini saxlayır. Bağlama hər bir müştəriyə bir IP ünvanı və bir sıra konfiqurasiya təyin etməkdən ibarətdir

Müəllifin kitabından

Statik Vəziyyət Dəyişən bəyannaməsində Static açar sözü, hətta prosedur işini başa vurduqdan sonra belə dəyişənin yaddaşda qalmasını istədiyiniz zaman istifadə edilməlidir - onun dəyərindən istifadə oluna bilsin. Aşağıdakı nümunədə dəyişən

Müəllifin kitabından

Bağlama Müştəri uzaq prosedura zəng etməzdən əvvəl o, tələb olunan serverə malik olan uzaq sistemə bağlanmalıdır. Beləliklə, məcburi vəzifə iki yerə bölünür:? Tələb olunan serverə malik uzaq host tapırsınız? Tapmaq

Müəllifin kitabından

9.1.7. Təhlükəsiz bağlama A Həddindən artıq yükləmədən istifadə edərkən, proqramın müxtəlif parametr siyahıları ilə eyni adlı bir neçə funksiyası ola biləcəyi görünür. Lakin bu leksik rahatlıq yalnız mənbə mətn səviyyəsində mövcuddur. Əksəriyyətdə

Müəllifin kitabından

Yığında statik yaddaşın ayrılması İstifadəçi məkanında bir çox yaddaş bölgüsü əməliyyatları, xüsusən də əvvəllər müzakirə olunan bəzi nümunələr stekdən istifadə etməklə həyata keçirilə bilər, çünki ayrılmış yaddaş bölgəsinin ölçüsü aprior olaraq bilinir. IN

data . Obyekt yönümlü proqramlaşdırmaya tətbiq edilən polimorfizmin məqsədi sinif üçün ümumi hərəkətləri müəyyən etmək üçün vahid addan istifadə etməkdir.

Java-da obyekt dəyişənləri polimorfikdir. Misal üçün:
sinif King ( ictimai statik boşluq əsas(String args) ( King king = new King() ; king = new AerysTargaryen() ; king = new RobertBaratheon() ; ) ) class RobertBaratheon genişləndirir King ( ) class AerysTargaryen King'i ( ) genişləndirir
King tipli dəyişən ya King tipli obyektə, ya da King-in hər hansı alt sinifinin obyektinə istinad edə bilər.
Aşağıdakı misalı götürək:

sinif Kralı ( ictimai boş nitq() ( Sistem .out .println ("Mən Andalların Kralıyam!" ); ) ictimai boşluq nitqi(Simli sitat) ( Sistem .out .println ("Müdrik adam dedi: " + sitat) ; ) ictimai etibarsız nitq(Boolean Loudly danışın) ( if (Loudly danışın) Sistem .out .println ( "MƏN ANDALLARIN KRALIYAM!!!11"); else System .out .println ("i"m... the king..." ) ; ) ) sinif AerysTargaryen King'i genişləndirir ( @İctimai boşluq nitqini ləğv edin() ( System .out .println ("Hamısını yandırın... " ) ; ) @İctimai etibarsız nitqi ləğv edin(String kotirovkası) ( System .out .println (quotation+ " ... Və indi hamısını yandırın!" ) ; ) ) class Kingdom ( ictimai statik boşluq əsas(String args) ( King king = yeni AerysTargaryen() ; king.speech ("Homo homini lupus est" ) ; ) )
Obyektə aid metod çağırıldıqda nə baş verir kral?

1. Kompilyator elan edilmiş obyekt tipini və metod adını yoxlayır, bütün metodları adla nömrələyirçıxış AerusTargarien sinfində və bütün ictimai üsullar super siniflərdə nitq
AerusTargarien. Kompilyator indi metodu çağırarkən mümkün namizədləri tanıyır.
2. Kompilyator metoda ötürülən arqumentlərin növlərini müəyyən edir. İmzası arqumentlərə uyğun gələn tək metod tapılarsa, çağırış edilir.Bu prosesking.speech("Homo homini lupus est") kompilyator metodu seçəcəknitq (simli sitat), amma yox çıxış().

Əgər kompilyator bir neçə üsul tapırsauyğun parametrlərlə (və ya heç biri) səhv mesajı göstərilir.



Kompilyator indi çağırılacaq metodun parametrlərinin adını və növlərini bilir.
3. Çağırılan metod olduqdaözəl, statik, finalvə ya konstruktor, statik bağlama istifadə olunur ( erkən bağlama). Digər hallarda, çağırılacaq üsul, çağırışın baş verdiyi obyektin faktiki növü ilə müəyyən edilir. Bunlar. proqramın icrası zamanı istifadə olunur dinamik bağlama (gec bağlama).

4. Virtual maşın hər bir sinif üçün bütün metodların imzalarını və çağırılacaq faktiki metodları sadalayan metod cədvəlini əvvəlcədən yaradır.
Bir sinif üçün metodlar cədvəliKral belə görünür:
  • çıxış() - Kral.çıxış()
  • nitq (simli sitat) -Kral. nitq (simli sitat)
  • Kral. nitq (Bul dilində yüksək səslə danış)
Və sinif üçünAerysTargaryen - bu kimi:
  • çıxış() - AerysTargaryen . çıxış()
  • nitq (simli sitat) - AerysTargaryen. nitq (simli sitat)
  • nitq(Bul dilində yüksək səslə danış) -Kral. nitq (Bul dilində yüksək səslə danış)
Obyektdən miras alınan metodlar bu nümunədə nəzərə alınmır.
Zəng edəndəkral.çıxış():
  1. Dəyişənin faktiki növü müəyyən edilirkral . Bu halda belədirAerysTargaryen.
  2. Virtual maşın metodun aid olduğu sinfi müəyyən edirçıxış()
  3. Metod deyilir.
Bütün üsulları birləşdirinJavagec bağlanma yolu ilə polimorf şəkildə həyata keçirilir.Dinamik bağlamanın bir mühüm xüsusiyyəti var: imkan verirkodlarını yenidən tərtib etmədən proqramları dəyişdirin. Proqramlar bunu edirdinamik olaraq genişləndirilə bilən ( genişlənən).
Konstruktorda qurulmuş obyektin dinamik bağlı metodunu çağırsanız nə olar? Misal üçün:
sinif King ( King () ( Sistem . out . println ( "Kral konstruktorunu çağırın" ) ; çıxış (); //AerysTargaryen-də polimorfik metod ləğv edilib) ictimai etibarsız nitq() ( System .out .println ("Mən Andalların Kralıyam!" ) ; ) ) sinif AerysTargaryen King'i genişləndirir ( şəxsi String qurbanı; AerysTargaryen() ( System .out .println ( "Aerys Targaryen konstruktorunu çağırın"); qurbanName = "Lyanna Stark" ; çıxış(); ) @İctimai etibarsız nitqi ləğv et() ( Sistem .out .println ("Yandır" + qurbanın adı + "!" ) ; ) ) sinif Krallığı ( ictimai statik boşluq əsas(String args) ( Kral kral = yeni AerysTargaryen() ; ) ) Nəticə:

Kral konstruktoruna zəng edin Yandırın sıfır! Aerys Targaryen konstruktoru Burn Lyanna Stark-a zəng edin!
Alınan sinifin qurulması zamanı baza sinfinin konstruktoru həmişə çağırılır. Zəng avtomatik olaraq miras zəncirində yuxarı hərəkət edir ki, miras zəncirində bütün əsas siniflərin konstruktorları nəhayət çağırılır.
Bu o deməkdir ki, konstruktoru çağırarkən yeni AerysTargaryen() çağırılacaq:
  1. yeni Obyekt()
  2. yeni kral()
  3. yeni AerysTargaryen()
Tərifə görə, dizaynerin işi obyektə həyat verməkdir. İstənilən konstruktorun daxilində obyekt yalnız qismən formalaşa bilər – yalnız əsas sinif obyektlərinin işə salınması məlumdur. Əgər konstruktor bu konstruktorun sinfindən əldə edilmiş sinif obyektinin qurulması istiqamətində atılan növbəti addımdırsa, cari konstruktor çağırıldığı anda “alınmış” hissələr hələ işə salınmayıb.

Bununla belə, dinamik bağlı çağırış iyerarxiyanın "xarici" hissəsinə, yəni törəmə siniflərə gedə bilər. Əgər o, konstruktorda törəmə sinif metodunu çağırırsa, bu, işə salınmamış verilənlərin manipulyasiyasına gətirib çıxara bilər ki, biz bu nümunənin çıxışında görürük.

Proqramın nəticəsi obyektin başlanğıc alqoritminin icrası ilə müəyyən edilir:

  1. Yeni obyekt üçün ayrılmış yaddaş binar sıfırlarla doldurulur.
  2. Baza sinfi konstruktorları əvvəllər təsvir olunan ardıcıllıqla çağırılır. Bu nöqtədə ləğv edilmiş metod çağırılırçıxış() (bəli, sinif konstruktorunu çağırmadan əvvəlAerysTargaryen), burada dəyişənin aşkar edildiyi Qurbanın adı sıfırdır birinci mərhələyə görə.
  3. Sinif üzvünün başlatıcıları təyin olunduqları ardıcıllıqla çağırılır.
  4. Alınan sinif konstruktorunun gövdəsi yerinə yetirilir.
Xüsusilə, bu cür davranış problemlərinə görə konstruktorların yazılması üçün aşağıdakı qaydaya riayət etməyə dəyər:
- obyekti işə salmaq üçün konstruktorda yalnız ən zəruri və sadə hərəkətləri yerinə yetirmək
- mümkünsə, olaraq təyin olunmayan çağırış metodlarından çəkininözəl və ya yekun (bu kontekstdə eyni şeydir).
İstifadə olunan materiallar:
  1. Ekkel B. - Java-da düşünmək , 4-cü nəşr - 8-ci fəsil
  2. Cay S. Horstmann, Gary Cornell -Əsas Java 1 - Fəsil 5
  3. Vikipediya

PHP 5.3.0-dan başlayaraq, statik varislik kontekstində çağırıla bilən sinfə istinad əldə etmək üçün istifadə edilə bilən gec statik bağlama adlı bir xüsusiyyət mövcud idi.

Daha dəqiq desək, gec statik bağlama son “yönləndirilməmiş zəng”də göstərilən sinfin adını qoruyur. Statik zənglər vəziyyətində bu, açıq şəkildə müəyyən edilmiş sinifdir (adətən operatorun solunda :: ); qeyri-statik çağırışlar zamanı bu obyektin sinfidir. "Yönləndirilmiş zəng" ilə başlayan statik zəngdir özü ::, valideyn::, statik::, və ya sinif iyerarxiyasını yuxarı qaldırsaq, irəli_statik_zəng(). Funksiya get_called_class()çağırılan sinfin adı ilə sətir əldə etmək üçün istifadə edilə bilər və statik::əhatə dairəsini ifadə edir.

"Gecikmiş statik bağlama" adı özü bu xüsusiyyətin daxili həyata keçirilməsini əks etdirir. "Gecikmiş bağlama" vasitəsilə zəng edən faktı əks etdirir statik::çağırılan metodun müəyyən edildiyi sinifə nisbətən hesablanmayacaq, lakin icra zamanı məlumat əsasında hesablanacaq. Bu xüsusiyyət həm də "statik bağlama" adlanırdı, çünki statik üsullarda istifadə edilə bilər (lakin məcburi deyil).

Məhdudiyyətlər özü ::

Nümunə №1 İstifadə özü ::

sinif A(
əks-səda __CLASS__ ;
}
ictimai statik funksiya
test()(
öz::kim();
}
}

B sinfi A-nı genişləndirir (
ictimai statik funksiya who() (
echo __CLASS__ ;
}
}

B::test();
?>

Gec Statik Bağlamadan istifadə

Daha sonra statik bağlama birbaşa iş vaxtında çağırılan sinfə istinad edən açar söz təqdim etməklə bu məhdudiyyəti aradan qaldırmağa çalışır. Sadəcə olaraq, əlaqə yaratmağa imkan verəcək açar söz B-dan test()əvvəlki misalda. Yeni açar söz təqdim etmək deyil, istifadə etmək qərara alındı statik, bu artıq rezerv edilib.

Nümunə №2 İstifadəsi asandır statik::

sinif A(
ictimai statik funksiya who() (
əks-səda __CLASS__ ;
}
ictimai statik funksiya
test()(
statik::kim(); // Burada gec statik bağlama tətbiq edilir
}
}

B sinfi A-nı genişləndirir (
ictimai statik funksiya who() (
echo __CLASS__ ;
}
}

B::test();
?>

Bu nümunəni işlətməyin nəticəsi:

Şərh:

Qeyri-statik kontekstdə çağırılan sinif obyekt nümunəsinin aid olduğu sinif olacaqdır. Çünki $this-> istifadə edərək, eyni əhatədən özəl metodları çağırmağa çalışacaq statik:: fərqli nəticələr verə bilər. Başqa bir fərq ondan ibarətdir ki statik:: yalnız sinfin statik sahələrinə istinad edə bilər.

Nümunə №3 İstifadə statik:: qeyri-statik kontekstdə

sinif A(
özəl funksiya foo() (
echo "uğur!\n" ;
}
ictimai funksiya testi() (
$this -> foo();
statik::foo();
}
}

B sinfi A-nı genişləndirir (
/* foo() B-yə kopyalanacaq, ona görə də onun əhatə dairəsi hələ də A-dır,
və zəng uğurlu olacaq*/
}

C sinfi A-nı genişləndirir (
özəl funksiya foo() (
/* orijinal metod dəyişdirildi; yeni C metodunun əhatə dairəsi */
}
}

$b = yeni B();
$b -> test();
$c = yeni C();
$c -> test(); //doğru deyil
?>

Bu nümunəni işlətməyin nəticəsi:

uğur! uğur! uğur! Ölümcül xəta: 9-cu sətirdə /tmp/test.php-də "A" kontekstindən şəxsi C::foo() metoduna zəng edin

Şərh:

Gecikmiş statik bağlamanın həlledici bölgəsi onu hesablayan statik çağırışla müəyyən ediləcək. Digər tərəfdən, kimi direktivlərdən istifadə edərək statik zənglər valideyn:: və ya özü :: zəng məlumatını yönləndirin.

Nümunə #4 Yönləndirilmiş və yönləndirilməyən zənglər

Bağlama- xüsusi funksiya çağırışlarının proqram kodlarına dəyişdirilməsi - sinif üsulları. Yalnız törəmə siniflər üçün məna kəsb edir.

Adətən kompilyator hansı funksiyanın nəzərdə tutulduğunu müəyyən etmək üçün lazımi məlumatlara malikdir. Məsələn, proqram obj.f() çağırışı ilə qarşılaşarsa, kompilyator təyinat obyektinin növündən asılı olaraq f() funksiyasını unikal şəkildə seçir. Əgər proqram sinif nümunələri üçün göstəricilərdən istifadə edirsə:ptr->f(), funksiya - sinif metodunun seçimi göstəricinin növü ilə müəyyən edilir.

Əgər funksiya seçimi kompilyasiya zamanı edilirsə, biz bununla məşğul oluruq statik əlaqə.

Bu halda, baza sinfinin göstəricisinə törəmə sinfin misalının ünvanının qiyməti təyin edilsə belə, baza sinfinin göstəricisi üçün funksiya - baza sinfinin metodu çağırılacaq.

Funksiya seçimi proqramın icra mərhələsində həyata keçirilirsə, biz bununla məşğul oluruq dinamik əlaqə.

Bu halda, proqramın icrası zamanı baza sinfinin göstəricisinə baza sinfinin nümunəsinin ünvanı təyin edilirsə, əsas sinif metodu çağırılacaq; Baza sinfinin göstəricisinə törəmə sinfin nümunəsinin ünvanı təyin edilərsə, törəmə sinfin metodu çağırılacaq.

Virtual funksiyalar

Varsayılan olaraq, törəmə siniflər statik olaraq bağlıdır. Hər hansı bir sinif metodları üçün dinamik bağlama istifadə ediləcəksə, belə üsullar elan edilməlidir virtual .

Virtual funksiyalar:

    əsas sinifdə prototipdə virtual açar sözə sahib olmaq;

    məcburi sinif üzvü funksiyaları:

    Bütün törəmə siniflər eyni prototipə malik olmalıdır (alınmış siniflərdə virtual sözünün göstərilməsinə ehtiyac yoxdur).

Əgər törəmə siniflərdəki hər hansı metodun adı əsas sinifdəki kimidirsə, lakin parametrlər siyahısı fərqlidirsə, biz funksiyaları həddən artıq yükləmişik.

Nümunə: Point və Circle sinifləri.

virtual boş çap ();

sinif dairəsi: ictimai nöqtə(

boş çap (); // siz virtual çapı ləğv edə bilərsiniz();

void Point::print()

cout<< "Point (" << x << ", " << y << ")";

void Circle::print()

cout<< "Circle with center in "; Point::print();

cout<< "and radius " << rad;

İstifadəsi:

p1(3,5), p2(1,1), *pPtr nöqtəsi;

Cicle c1(1), c2(p2, 1);

pPtr = pPtr->print(); // alın: Nöqtə (3, 5)

pPtr = pPtr->print(); // almaq:

Mərkəzi (1, 1) nöqtəsində və radiusu 1 olan dairə

Dinamik Bağlama Misal: Siyahı

Dinamik bağlamanın ən ümumi istifadəsi baza sinfinə göstərici olan konteyner sinifləridir; Belə konteyner sinifləri həm əsas, həm də hər hansı törəmə siniflərlə əlaqəli məlumatları ehtiva edə bilər.

Nümunəni nəzərdən keçirək - həm nöqtələri, həm də dairələri ehtiva edən bir siyahı.

// konstruktor

Maddə():info(NULL), sonrakı(NULL)()

Maddə(Nöqtə *p):info(p), sonrakı(NULL)()

Siyahı():baş(NULL)()

boşluq əlavəsi(Nöqtə *p)(p->növbəti = baş; baş = p;)

boş Siyahı::print()

üçün(İtem *cur = baş; cur; cur = cur->növbəti)(

cur->info->print();

cout<< endl;

Sinifdən istifadə:

Nöqtə *p = yeni Nöqtə(1,2);

mylist.insert(p);

p = yeni Dövr(1,2,1);

mylist.insert(p);

Mərkəzi (1, 2) nöqtəsində və radiusu 1 olan dairə

Həddindən artıq statik rabitə səviyyələrinin tətbiqlərə və sistem performansına böyük müsbət təsir göstərə biləcəyi çoxlu və artan sayda sistemlər var.

Mən tez-tez "yerləşdirilmiş sistemlər" adlanan şeylərdən danışıram, onların bir çoxu indi getdikcə daha çox ümumi təyinatlı əməliyyat sistemlərindən istifadə edir və bu sistemlər təsəvvür edilən hər şey üçün istifadə olunur.

Çox yayılmış bir nümunə, Busybox istifadə edərək GNU/Linux sistemlərindən istifadə edən qurğulardır. Mən bunu NetBSD ilə həddindən artıq dərəcədə etmişəm ki, həm nüvəni, həm də onun kök fayl sistemini özündə cəmləşdirən yüklənə bilən i386 (32-bit) sistem təsviri yaradaraq, bütün proqramlara sərt keçidləri olan bir statik (crunchgen vasitəsilə) ikili fayl sistemini ehtiva edir. ehtiva edir hamısı(yaxşı, nəhayət 274 sayın) (bunun çoxu alətlər silsiləsi istisna olmaqla) və bu 20-dən azdır meqa bayt (və yəqin ki, 64 MB yaddaşa malik sistemdə çox rahat işləyir (hətta kök fayl sistemi sıxılmamış və tamamilə RAM-da olsa da), sınaqdan keçirmək üçün o qədər də kiçik tapa bilmədim).

Əvvəlki yazılarda qeyd olunurdu ki, statik əlaqəli ikili faylların işə salınma vaxtı daha sürətlidir (və bu, daha sürətli ola bilər), lakin bu, şəklin yalnız bir hissəsidir, xüsusən də bütün obyekt kodu eyni faylda birləşdirildikdə və daha çox əməliyyat sistemi birbaşa icra olunan fayldan dəyişdirmə sorğusu kodunu dəstəkləyir. Bu ideal ssenaridə, proqramın işə salınma vaxtları sözün əsl mənasında əhəmiyyətsizdir, çünki kodun demək olar ki, bütün səhifələri artıq yaddaşdadır və tələb olunan proqram heç vaxt işləməsə belə, shell tərəfindən istifadə olunacaq (və işləyə biləcək hər hansı digər fon prosesləri tərəfindən başlanğıc). yükləndikdən sonra işə salınıb, çünki proqramın icra müddəti tələblərinə cavab vermək üçün yüklənmiş yaddaşın yalnız bir səhifəsi ola bilər.

Ancaq bu, bütün hekayə deyil. Mən həmçinin bütün ikili faylları statik olaraq birləşdirərək, tam inkişaf sistemlərim üçün adətən NetBSD əməliyyat sistemi quraşdırmasını qururam və istifadə edirəm. Bunun üçün böyük həcmdə disk sahəsi tələb olunsa da (x86_64 üçün cəmi ~6,6 GB, alətlər silsiləsi və X11 statik əlaqəli hər şey daxil olmaqla) (xüsusilə bütün proqramlar üçün tam sazlama simvolu cədvəllərini ~2 daha çox .5 GB üçün əlçatan edirsinizsə), nəticə ümumi olaraq hələ də daha sürətlidir və bəzi tapşırıqlar hətta kitabxananın kod səhifələrini mübadilə etmək üçün nəzərdə tutulmuş adi dinamik əlaqəli sistemdən daha az yaddaş istifadə edir. Disk ucuzdur (hətta sürətli diskdir) və diskdə tez-tez istifadə olunan faylları keşləmək üçün yaddaş da nisbətən ucuzdur, lakin CPU dövrləri həqiqətən belə deyil və hər başlayanda başlayan hər proses üçün ld.so-nun ilkin qazancını ödəmək saatlar çəkəcək. və bir çox proseslərin icrasını tələb edən tapşırıqlardan, xüsusən də eyni proqramlar, məsələn, inkişaf sistemindəki kompilyatorlar kimi təkrar-təkrar istifadə edildikdə, CPU dövrü saatları. Statik paketli proqram proqramları bütün sistem üçün multicast arxitekturasını yaratmaq üçün lazım olan vaxtı saatlarla azalda bilər. Alətlər silsiləsində hələ də tək crunchgen"ed binar sistemimdə qurmalıyam, lakin mən şübhələnirəm ki, bunu etdikdə CPU önbelleği üçün qazanc sayəsində daha çox tikinti vaxtı qənaət olunacaq.