2011-03-23 10 views
8

Diciamo che ho il seguente codice in ciò che ci aspettiamo di diventare il prossimo standard C++:Ereditare costruttori in C++ 0x

int f(int x) 
{ 
    std::cout << x; 
    return x * x; 
} 

struct A 
{ 
    A(int x) : m_x(x) {} 
    int m_x; 
}; 

struct B : A 
{ 
    using A::A; 
    B() : m_y(f(m_x)) {} 
    int m_y; 
}; 

int main() 
{ 
    B(5); 
} 

sarebbe questo chiamare il costruttore di default di B e stampare 5 e impostare m_y = 25? O il costruttore predefinito di B non verrà eseguito e lascerà m_y non inizializzato?

E se quest'ultimo, qual è la logica dietro non chiamare il costruttore B predefinito? È abbastanza chiaro che A (int) B eredita solo inizializza A e lascia B in uno stato indeterminato. Perché C++ dovrebbe scegliere un comportamento non definito semplicemente chiamando il costruttore predefinito di B()? In gran parte sconfigge lo scopo della caratteristica dei costruttori ereditari.

Edit:

Forse questo dovrebbe essere consentito:

using A::A : m_y(...) { std::cout << "constructing..." << std::endl; ...; } 
+1

m_y sarà inizializzato, utilizzando A :: A, è otterrà qualcosa di simile a questo: B :: B (int x): A :: m_x (x) {}. O qualcosa :) – hidayat

+0

C++ sceglie effettivamente di compilare il codice con errore in quanto non si fornisce il costruttore predefinito per A. È _non_ un comportamento non definito :) – user396672

risposta

4

using A::A; dichiara implicitamente B(int) nella classe derivata. È così.

Il resto del programma non dovrebbe funzionare come previsto. Perché stai invocando B(int) con B(5) e questo lascia m_y non inizializzato.

Vedere questo esempio dal sito di Bjarne Stroustrup:

struct B1 { 
    B1(int) { } 
}; 

struct D1 : B1 { 
    using B1::B1; // implicitly declares D1(int) 
    int x; 
}; 

void test() 
{ 
    D1 d(6); // Oops: d.x is not initialized 
    D1 e;  // error: D1 has no default constructor 
} 

http://www2.research.att.com/~bs/C++0xFAQ.html#inheriting

Un altro esempio dallo stesso link:

struct D1 : B1 { 
     using B1::B1; // implicitly declares D1(int) 
     int x{0}; // note: x is initialized 
    }; 

    void test() 
    { 
     D1 d(6); // d.x is zero 
    } 
+0

Se D1 aveva un costruttore predefinito, sarebbe eseguito quando esegue la linea " D1 d (6); "? – Clinton

+0

Il suo esempio non ha dichiarato un costruttore predefinito per D1. Ovviamente x non verrà inizializzato, indipendentemente dall'utilizzo di "B1: B1". Il mio esempio tuttavia dichiara un costruttore predefinito. – Clinton

+0

@Clinton: Sì. Ma il costruttore predefinito non è invocato nel tuo esempio. Quindi non importa se lo si definisce o no, si invoca il costruttore implicitamente dichiarato che è 'B (int)' nel proprio esempio. – Nawaz