Koja su pravila za pozivanje konstruktora superklasa?

Koja su pravila C ++ za pozivanje konstruktora superklase iz podrazreda?

Na primjer, znam u Javi da to učinite kao prvi redak konstruktora potklasa (i ako to ne učinite, implicitno nazovite ne-arg superstruktora), koji će vam dati pogrešku kompilacije ako nešto nedostaje).

495
23 сент. postavila levik na 23 ruj . 2008-09-23 16:09 '08 u 16:09 2008-09-23 16:09
@ 9 odgovora

Konstruktori bazne klase automatski se pozivaju na vas ako nemaju argumente. Ako želite pozvati konstrukt superklase s argumentom, morate koristiti inicijalizacijski popis konstruktora podrazreda. Za razliku od Java-a, C ++ podržava višestruko nasljeđivanje (za bolje ili lošije), tako da se osnovna klasa naziva po imenu, a ne "super ()".

 class SuperClass { public: SuperClass(int foo) { // do something with foo } }; class SubClass : public SuperClass { public: SubClass(int foo, int bar) : SuperClass(foo) // Call the superclass constructor in the subclass' initialization list. { // do something with bar } }; 

Saznajte više o popisu inicijalizacije konstruktora ovdje i ovdje .

692
23 сент. odgovor luke ruj 23. \ t 2008-09-23 16:18 '08 u 16:18 2008-09-23 16:18

U C ++, konstruktori bez argumenata za sve superklase i varijable članova pozivaju se prije nego što unesete konstruktora. Ako želite proslijediti njihove argumente, postoji posebna sintaksa za ovo, nazvana "lanac konstruktora", koja izgleda ovako:

 class Sub : public Base { Sub(int x, int y) : Base(x), member(y) { } Type member; }; 

Ako nešto počne u tom trenutku, baze / članovi koji su ranije dovršili izgradnju uzrokovali su svoje destruktore, a iznimka je upućena pozivatelju. Ako tijekom ulančavanja želite uhvatiti iznimke, morate koristiti blok funkcije try:

border=0
 class Sub : public Base { Sub(int x, int y) try : Base(x), member(y) { // function body goes here } catch(const ExceptionType  { throw kaboom(); } Type member; }; 

U ovom obliku imajte na umu da je try blok tijelo funkcije, a ne unutar tijela funkcije; to mu omogućuje da uhvati iznimke uzrokovane implicitnim ili eksplicitnim inicijalizacijama članova i osnovne klase, kao i tijekom tijela funkcije. Međutim, ako blok catch funkcije ne generira drugu iznimku, vrijeme izvođenja će ponovno pokrenuti izvornu pogrešku; iznimke inicijalizacije ne mogu se zanemariti.

170
23 сент. odgovor dati puetzk 23. ruj. \ t 2008-09-23 16:22 '08 u 16:22 2008-09-23 16:22

U C ++ postoji koncept popisa inicijalizatora konstruktora, gdje možete i trebate pozvati konstruktora osnovne klase i gdje također trebate inicijalizirati elemente podataka. Popis inicijalizacije pojavljuje se nakon potpisivanja konstruktora nakon dvotačke i pred tijelom konstruktora. Neka se kaže da imamo klasu A:

 class A : public B { public: A(int a, int b, int c); private: int b_, c_; }; 

Zatim, ako B ima konstruktor koji prihvaća int, konstruktor može izgledati ovako:

 A::A(int a, int b, int c) : B(a), b_(b), c_(c) // initialization list { // do something } 

Kao što možete vidjeti, konstruktor osnovne klase se poziva na popisu inicijalizacije. Inicijaliziranje elemenata podataka u listi inicijalizacije, usput, poželjno je dodijeliti vrijednosti za b_ i c_ unutar tijela konstruktora, budući da ćete uštedjeti dodatne troškove zadatka.

Imajte na umu da su članovi podataka uvijek inicijalizirani redoslijedom kojim su deklarirani u definiciji klase, bez obzira na njihov redoslijed na inicijalizacijskom popisu. Da biste izbjegli čudne pogreške koje se mogu pojaviti ako vaši članovi podataka ovise jedni o drugima, uvijek biste se trebali pobrinuti da je redoslijed članova isti na popisu inicijalizacije i definiciji klase. Iz istog razloga, konstruktor osnovne klase mora biti prvi element na popisu inicijalizacije. Ako ga uopće izostavite, zadani konstruktor za osnovnu klasu bit će pozvan automatski. U ovom slučaju, ako osnovna klasa nema zadani konstruktor, dobit ćete kompilacijsku pogrešku.

38
23 сент. Odgovor je dan Dima 23. rujna. 2008-09-23 16:34 '08 u 16:34 2008-09-23 16:34

Jedini način prosljeđivanja vrijednosti roditeljskom konstruktoru je popis inicijalizacije. Inicijalizacijski popis implementira se pomoću: i zatim popisa klasa i vrijednosti koje se moraju proslijediti ovom konstruktoru klase.

 Class2::Class2(string id) : Class1(id) { .... } 

Također zapamtite da ako imate konstruktora koji ne prihvaća parametre roditeljske klase, bit će automatski pozvan prije izvršenja izvršnog konstruktora.

16
Odgovor je CR. 23. rujna 2008-09-23 16:21 '08 u 16:21 2008-09-23 16:21

Ako imate konstruktora bez argumenata, on će biti pozvan prije izvođenja konstruktora izvedene klase.

Ako želite pozvati osnovni konstruktor s argumentima, morate to izričito napisati u izvedenom konstruktoru na sljedeći način:

 class base { public: base (int arg) { } }; class derived : public base { public: derived () : base (number) { } }; 

Ne možete izgraditi izvedenu klasu bez pozivanja nadređenog konstruktora u C ++. To se događa automatski, ako je C'tor ne-argument, to se događa ako pozovete izvedeni konstruktor izravno, kao što je prikazano gore, ili se vaš kod neće prevesti.

14
23 сент. Odgovor daje Nils Pipenbrinck 23. rujna 2008-09-23 16:19 '08 u 16:19 2008-09-23 16:19

Svi su spomenuli poziv konstruktora kroz inicijalizacijski popis, ali nitko nije rekao da se konstruktor roditeljske klase može izričito pozvati iz tijela izvedenog člana. Vidi pitanje Na primjer, pozivanje konstruktora osnovne klase iz tijela konstruktora podrazreda . Činjenica je da ako koristite eksplicitan poziv nadređenom razredu ili konstruktu superklase u tijelu izvedene klase, on zapravo jednostavno kreira instancu roditeljske klase i ne poziva konstruktora roditeljske klase na izvedeni objekt, jedini način da se pozove roditeljska klasa ili konstruktor nadklasa u izvedenom objektu class - kroz inicijalizacijski popis, a ne u tijelo konstruktora izvedene klase. Stoga je moguće da se ne može nazvati "pozivom na konstruktora superklase". Stavio sam ovaj odgovor ovdje jer bi se netko mogao zbuniti (poput mene).

10
28 янв. odgovor je dan TT_ Jan 28 2014-01-28 01:04 '14 u 1:04 2014-01-28 01:04

Ako imate zadane parametre u osnovnom konstruktoru, osnovna klasa će biti pozvana automatski.

 using namespace std; class Base { public: Base(int a=1) : _a(a) {} protected: int _a; }; class Derived : public Base { public: Derived() {} void printit() { cout << _a << endl; } }; int main() { Derived d; d.printit(); return 0; } 

Izlaz: 1

7
15 июля '14 в 21:49 2014-07-15 21:49 odgovor je dan edW 15. srpnja 14. u 21:49 2014-07-15 21:49
 CDerived::CDerived() : CBase(...), iCount(0) //this is the initialisation list. You can initialise member variables here too. (eg iCount := 0) { //construct body } 
6
23 сент. Odgovor je dan Dynite 23. rujna 2008-09-23 16:24 '08 u 16:24 2008-09-23 16:24

Nitko nije spominjao redoslijed poziva konstruktora kada je klasa izvedena iz nekoliko klasa. Redoslijed, kao što je spomenuto u izvedbi klasa.

1
12 марта '14 в 13:46 2014-03-12 13:46 odgovor je darth_coder 12. ožujka 2014. u 13:46 2014-03-12 13:46

Ostala pitanja o oznakama ili postavljanja pitanja