2010-05-02 10 views
5

Mam zestaw kodu, który naśladuje podstawowy system katalogowania biblioteki. Istnieje klasa bazowa o nazwie items, w której zdefiniowane są ogólne identyfikatory, tytuł i rok oraz 3 inne klasy pochodne (DVD, Book i CD).Pomoc w przypadku tych ostrzeżeń. [dziedziczenie]

bazowego [książki]

Pochodzące [DVD, książki, CD].

Programy działają, jednak otrzymuję następujące ostrzeżenia, nie jestem pewien, jak je naprawić.

 
>"C:\Program Files\gcc\bin/g++" -Os -mconsole -g -Wall -Wshadow -fno-common mainA4.cpp -o mainA4.exe 
In file included from mainA4.cpp:5: 
a4.h: In constructor `DVD::DVD(int, std::string, int, std::string)': 
a4.h:28: warning: `DVD::director' will be initialized after 
a4.h:32: warning: base `Items' 
a4.h:32: warning: when initialized here 
a4.h: In constructor `Book::Book(int, std::string, int, std::string, int)': 
a4.h:48: warning: `Book::numPages' will be initialized after 
a4.h:52: warning: base `Items' 
a4.h:52: warning: when initialized here 
a4.h: In constructor `CD::CD(int, std::string, int, std::string, int)': 
a4.h:66: warning: `CD::numSongs' will be initialized after 
a4.h:70: warning: base `Items' 
a4.h:70: warning: when initialized here 
>Exit code: 0 

Odpowiedz

28

Po zadeklarowaniu zmiennych członków w klasie są one inicjowane w kolejności ich deklarowania. Ale możesz napisać je w dowolnej kolejności na liście inicjalizacyjnej swojego konstruktora. Na przykład,

struct foo { 
    int a; 
    int b; 

    foo(): b(5), a(3) {} 
}; 

wybuduje a i następnieb, choć wydaje się, że jesteś inicjowanie je w drugiej kolejności.

Kompilator wyświetla ostrzeżenie, ponieważ można się podstępem napisać niepoprawny kod. Na przykład,

struct foo { 
    int a; 
    int b; 

    foo(): b(5), a(b) {} 
}; 

wartość a będą niezdefiniowane.

+0

Dziękuję bardzo – silent

+0

Świetna odpowiedź, dzięki. –

3

Po zainicjowaniu elementów klasy w konstruktorze należy zainicjować je w tej samej kolejności, w jakiej zostały zadeklarowane. Np .:

class Foo { 
    public: 
    int a; 
    int b; 
    Foo() : a(0), b(0) {} 
}; 

W Foo() konstruktora, przełączanie kolejności a i b doprowadzi do ostrzeżeń. To samo dotyczy inicjowania klas bazowych (których konstruktory, jeśli są wywoływane jawnie, powinny zostać wywołane przed inicjalizatorami elementów danych).

6

Musisz rzucić okiem na swoich konstruktorów i listy inicjalizacji członków. Trudno powiedzieć, nie widząc kodu, ale to, co się dzieje, polega na tym, że masz taki kod: -

class my_class : public base1, public base2 
{ 
    public: 
     my_class(); 

    private: 
     member1 member1_; 
     member2 member2_; 
} 

my_class::my_class() 
    : member2_(...) 
    , member1_(...) 
    , base2_(...) 
    , base1_(...) 
{ } 

Spowoduje to podobne ostrzeżenia. Powodem jest to, że w C++ konstruktor zawsze konstruuje klasy bazowe w kolejności pokazanej na liście klasy bazowej (base1, a następnie base2), a następnie konstruuje zmienne składowe od góry do dołu w definicji klasy. Robi to bez względu na porządek, w którym określasz rzeczy na liście inicjowania członków - ta kolejność jest ignorowana, ale jeśli nie jest zgodna, niektóre kompilatory (w tym twój wydaje się) ostrzeże Cię o tym.

Powodem tego jest to, że C++ ma ścisłe wymaganie, aby destruktory były wywoływane w odwrotnej kolejności konstruktorów, więc jeśli robiłby rzeczy w kolejności list inicjalizacji członków, musiałby w jakiś sposób "pamiętać "który konstruktor został wywołany, aby mógł wywołać destruktory we właściwej kolejności. Nie robi tego, ale zamiast tego zawsze używa tej samej kolejności.