2010-10-22 7 views
5

jest możliwe przejście niezainicjowanego przedmiotu do grupy macierzystej, jak w poniższym przykładzieniezainicjowanego odniesienia do obiektu iniside konstruktora

class C 
{ 
    public: 
     C(int i): 
      m_i(i) 
     {}; 

     int m_i; 
} 

class T 
{ 
    public: 
     T(C & c): 
      m_c(c) 
     { 
     }; 

     C & m_c; 
}; 


class ST : public T 
{ 
    public: 
     ST(): 
      T(m_ci), 
      m_ci(999) 
     { 
     }; 

     C m_ci; 
}; 

W class T konstruktora c jest odniesienie do niezainicjowanego obiektu. Jeśli obiekt class T używałby obiektu c podczas budowy, może to prowadzić do błędu. Ale ponieważ nie jest, to kompiluje i działa dobrze. Moje pytanie brzmi: czy hamuje jakiś paradygmat lub dobre dyrektywy projektowe? Jeśli tak, jakie są alternatywy, ponieważ uznałem za przydatne przydzielić obiekt wymagany przez obiekt macierzysty w podklasie.

Zastanawiam się, dlaczego nie jest możliwa zmiana kolejności inicjalizacji, aby konstruktor klasy podstawowej został wywołany po inicjalizacji niektórych elementów.

Odpowiedz

2

Ty może , ale dostajesz niezdefiniowane zachowanie.

W narzędziach programu Boost znajdziesz base-from-member idiom utworzoną przez R. Samuel Klatchko. Zasadniczo tworzysz prywatną bazę w miejscu prywatnego członka. Ta baza zostanie najpierw zainicjalizowana i można jej użyć do innych baz:

Narzędzie Boost eliminuje powtarzanie kodu.

2

Widziałem to bardzo często, a wiele kompilatorów ostrzega. Jest ok, jeśli konstruktor T nigdy nie usuwa odwołania do odwołania c.

Jeśli nie chcesz ostrzeżenia, musisz wykonać dwustopniową konstrukcję. Zrób chroniony Init(C&) metodę w T, a następnie wywołać go w organizmie ST konstruktora - niestety m_c będą musiały być wskaźnikiem tego robić (od odniesienia nie może być przeniesiony do innego obiektu)

2

Przekazywanie odniesienia lub wskaźnika do czegoś niezainicjowanego jest technicznie całkowicie poprawne.

Ale powodem, dla którego pytasz, jest prawdopodobnie to, że coś łatwo może pójść nie tak, że przez pewien łańcuch połączeń można niechcący uzyskać dostęp do obiektu, zanim zostanie zainicjowany. I myślę, że to ważna sprawa. I jest jeszcze jedna rzecz, która może pójść źle, a mianowicie, że kod w klasie bazowej T mogą teraz być może unieważnić klasy niezmiennikiem ST bezpośrednio zmieniając człon danych ST przykład ...

Tak, myślę, że to trochę ryzykowne.

Jeśli chodzi o kolejność inicjalizacji, C++ opiera się na idei budowania z części w górę, w hierarchii. Jeśli konstruktor rzuca, wtedy całkowicie skonstruowane rzeczy są automatycznie niszczone. Byłoby to trudniejsze lub mniej skuteczne z bardziej arbitralnym porządkiem konstrukcyjnym.

Pozdrowienia & hth.,