Tengo las siguientes clases:
class A
{
public:
A();
A( int i );
protected:
int a;
};
class B : public A
{
public:
B();
B( int i );
protected:
int b;
};
Y quiero que cuando se construya una instancia de la clase B con el constructor B( int i ), el constructor de la clase B llame al constructor de la clase A con el parametro i (es decir llame a A( i ) ).
¿Es posible?
Saludos.
No se si entiendo bien tu pregunta, pero es muy sencillo:
class B : public A
{
public:
B();
B( int i ): A(i) { }
protected:
int b;
};
O si lo prefieres
class B : public A
{
public:
B();
B( int i ) {
A::A(i);
}
protected:
int b;
};
Personalmente, me gusta usar un convenio que puso Javier Arevalo (Jare) hace tiempo en flipcode (
http://www.flipcode.com/cgi-bin/msg.cgi?sh...orum=totd&id=-1) a la hora de acceder a la clase base (y usar un protocolo de inicializacion y finalizacion; yo he usado estas tecnicas en CrisolEngine y son fantasticas):
class B : public A
{
private:
// Tipos
// Acceso a clase base
typedef A Inherited;
public:
B();
B( int i ) {
Inherited::A(i);
}
protected:
int b;
};
Saludos.
Muchas gracias.
Uhm, el segundo caso NO es exactamente lo mismo, es análogo a usar lista de inicialización o asignaciones en un constructor.
Para llamar a un constructor en concreto con un parámetro, usa lo primero que ha puesto:
B(int i):A(i){}
Si haces:
B(int i)
{
A::A(i);
}
en este caso el al crear una instancia de la clase B, se llamará al constructor por defecto de A y después , en el constructor de A, se volverá a llamar a un constructor de A, el que recibe el parámetro.
En el primer caso, al crear un objeto del tipo B sucedería:
A(int i);
B(int);
/*Se llaman a estos 2 constructores*/
En el segundo caso:
A();
B(int i);
A(int i);/*Llamado explicitamente desde B(int i)*/
Todo es mucho más claro, legible y eficiente si se acostumbra uno a usar listas de inicializadores, lo mismo para variables como para los constructores.
Gracias Grugnorr por la explicación.
Saludos.
El segundo caso, además, está mal:
class A
{
protected:
int a;
public:
A() { a = 0; };
A( int i ) { a = i; };
};
class B : public A
{
protected:
int b;
public:
B() { b = 0; };
B( int i ) { A::A(i); };
int GetValue() { return a; };
};
B claseB(5);
int valor = claseB.GetValue();
y 'valor' vale 0 en vez de 5.
Cuando el segundo constructor de B hace A::A(i), lo que se está haciendo es crear un objeto temporal de A que inicializa la variable 'a' a 5 e inmediatamente después se destruye.
El constructor sobrecargado de B debería ser:
B( int i ) { this->A::A(i); };
o, ya puestos, como la variable en este caso está declarada como 'protected':
B( int i ) { this->a = i; };
Metaxas
Bueno, sin el this, simplemente poniendo:
B( int i ) { A(i); };
también valdría.
Saludos.
No, eso no compila, no puedes llamar al constructor de A sin el operador de ámbito.
Metaxas
mmm... lo puse porque creía que lo tenía puesto así, pero ahora que lo he mirado, lo que tengo es:
B::B( int i ) : A( i )
Saludos.