2008-12-07 20 views
148

¿Por qué este código:constructores

class A 
{ 
    public: 
     explicit A(int x) {} 
}; 

class B: public A 
{ 
}; 

int main(void) 
{ 
    B *b = new B(5); 
    delete b; 
} 

resultado de estos errores:

 
main.cpp: In function ‘int main()’: 
main.cpp:13: error: no matching function for call to ‘B::B(int)’ 
main.cpp:8: note: candidates are: B::B() 
main.cpp:8: note:     B::B(const B&) 

B No debe heredar el constructor de A?

(esto se utiliza gcc)

Respuesta

248

En C++ 03, los constructores estándar no se pueden heredar y debe heredarlos uno por uno llamando a la implementación base por su cuenta. Si su compilador es compatible con el estándar C++ 11, existe una herencia de constructor. Para más información, vea Wikipedia C++11 article. Con la nueva norma se escribe:

class A 
{ 
    public: 
     explicit A(int x) {} 
}; 

class B: public A 
{ 
    using A::A; 
}; 
+9

Esto es bastante mal, porque hace más de un año que ha habido un compilador que realmente puede construir el código anterior :-) – Mikhail

+11

@Mikhail: Tanto ruido metálico y g ++ ahora debe apoyar heredar constructores: http: // tañido .llvm.org/cxx_status.html http://gcc.gnu.org/projects/cxx0x.html Recomienda votar esta como la respuesta correcta. –

+0

preguntando, ¿un constructor heredado podría acceder/inicializar los miembros privados de la clase base? ¿O debería especificarlos como protegidos? – Markasoftware

4

Hay que definir explícitamente el constructor en B y llamar explícitamente al constructor de la matriz.

B(int x) : A(x) { } 

o

B() : A(5) { } 
80

Los constructores no se heredan. El constructor hijo los llama implícita o explícitamente.

El compilador crea un constructor predeterminado (uno sin argumentos) y un constructor de copia predeterminado (uno con un argumento que es una referencia del mismo tipo). Pero si quiere un constructor que acepte un int, debe definirlo explícitamente.

class A 
{ 
public: 
    explicit A(int x) {} 
}; 

class B: public A 
{ 
public: 
    explicit B(int x) : A(x) { } 
}; 

ACTUALIZACIÓN: En C++ 11, los constructores puede ser heredada. Ver la respuesta de Suma para más detalles.

1

código correcto es

class A 
{ 
    public: 
     explicit A(int x) {} 
}; 

class B: public A 
{ 
     public: 

    B(int a):A(a){ 
      } 
}; 

main() 
{ 
    B *b = new B(5); 
    delete b; 
} 

error es b/c Clase B tiene constructor no parámetro y el segundo debe tener inicializador de clase base para llamar al constructor de la clase base parámetro constructor

3

Ésta es directamente desde Bjarne Stroustrup's page:

Si así lo desea, puede seguir disparando en el pie por i nheriting constructores en una clase derivada en la que se definen nuevas variables miembro que necesitan inicialización:

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 
} 
+0

'int x = 77;' en lugar de 'int x;' resolvería el problema –

+0

@ BЈовић: Sí, esa es la frase siguiente en la página de Bjarne :) –

1

¿Cómo sobre el uso de una función de plantilla para unir todos los constructores?

template <class... T> Derived(T... t) : Base(t...) {} 
+2

Probablemente debería hacerlo con perfecta reenvío: plantilla B (Args && ... args) : a (std :: forward < Args > (args) ...) {} –

+0

Y acabas de romper el constructor de copias de 'Derived'. – Barry

+0

¿Tendría que modelarse también el constructor de Base? Cuando llamas a Base (t ...), entonces Base tendría que ser modelado para lo que sea t? – Zebrafish