2011-10-05 14 views
12

Una de las piedras angulares de OOP es reutilizar el código en lugar de repetirlo una y otra vez. Por lo tanto, sus proyectos se acortan y se vuelven más legibles.Constructores reutilizables C++

C++ le brinda todas las herramientas que necesita para reutilizar los métodos en lugar de repetir el código. Aunque cuando se trata de constructores, no sé cómo reutilizarlos.

Soy no hablando de patrimonio o cómo enviar un mensaje al padre. Estoy hablando de reutilizar el constructor de la clase en sí.

La analogía en JAVA es algo como esto:

public Foo() { 
    this(0,0,0);//Not needed in this case, just to clarify 
} 

public Foo(Foo f){ 
    this(f.getA(), f.getB(), f.getC()); 
} 

public Foo(int a, int b, int c) { 
    this.a = a; 
    this.b = b; 
    this.c = c; 
} 

Mi pregunta es, ¿hay alguna sintaxis en C++ que permite que lo haga?

Respuesta

8

This is possible with recently published C++11, pero ningún compilador de C++ implementa esta característica todavía.

+0

que ha sido criado un par de veces en la lista de Clang dev. Por lo que yo sé, se considera de baja prioridad porque no es tanto un cambio de vida como lambdas, por ejemplo. Por supuesto, si uno realmente lo considera útil, tanto Clang como gcc son de código abierto :) –

+0

Esta respuesta podría usar una actualización. –

6

C++ 11 ha agregado delegación de constructores y herencia de constructores. Sin embargo, necesitará obtener un compilador que lo admita.

Para heredar constructores, se requiere un usando-declaración:

class Base { ... }; 

class Derived : public Base 
{ 
    using Base::Base; 
}; 

Delegar, utilice el ctor-inicializador, pero especifique otro constructor de la misma clase, en lugar de los subobjetos (todo subobjetos base y miembros serán inicializados por el constructor delegado a):

class Another : public Base 
{ 
    int member; 
    Another(int x) 
     : Base(), member(x) // non-delegating constructor initializes sub-objects 
    {} 


    Another(void) 
     : Another(5) // delegates -- other constructor takes care of Base and member 
    {} 
}; 

y perfecto reenvío también puede ser útil.

+1

Esto ahora debería estar comúnmente disponible, quizás debería ser la respuesta aceptada ... – moodboom

11

Otros ya han respondido sobre C++ 11, pero para C++ 03 existe una posible solución alternativa: utilizar una clase base con los constructores necesarios.

struct foo_base { 
    foo_base(int a, int b, int c) : a(a), b(b), c(c) { } 
    int a, b, c; 
}; 

struct foo : foo_base { 
    foo() : foo_base(0, 0, 0) { } 
    foo(const foo& other) : foo_base(other.a, other.b, other.c) { } 
    foo(int a, int b, int c) : foo_base(a, b, c) { } 
}; 

Por supuesto, debe considerar si vale la pena el modelo para sus propósitos.

+2

+1 para señalar una solución con los compiladores existentes. –

+1

+1 por escribir lo que había decidido escribir, antes de decidir. –

2

El soultion generalmente aceptada para los compiladores actuales es que hacer esto:

class Bar{ 
pubilc:  
Foo() { 
    init(0,0,0); 
} 

Foo(const Foo &f){ 
    init(f.getA(), f.getB(), f.getC()); 
} 

Foo(int a, int b, int c) { 
    init(a,b,c); 
} 

private: 

void init(int a, int b, int c){ 
    this->a = a; 
    this->b = b; 
    this->c = c; 
} 
}; 

Si bien esto puede parecer más de matar en este ejemplo, es sólo debido a la simplicidad del ejemplo. En una aplicación del mundo real, esto aportaría beneficios en términos de reducción del código repetido.

+0

¿Qué idioma es este? – Johnsyweb

+0

Lo siento, java y C++ difuminan juntos a veces a veces. Edité mi publicación para que esté completamente en C++ válido ahora suponiendo que tiene funciones getA(), getB(), getC() válidas. –

+1

'this.a' no es válido, y el constructor de copia debe tomar referencia const como argumento. –

1

OK C++ 11 cubre lo que necesita.

Pero su caso simple tiene una solución fácil:

/* This one is covered by providing default parameters see below. 
public Foo() { 
    this(0,0,0);//Not needed in this case, just to clarify 
} 

This is done automatically by the compiler. 
You do not need to write any code for this: 
public Foo(Foo f){ 
    this(f.getA(), f.getB(), f.getC()); 
} 
The compiler generated version actually looks like this: 
public Foo(Foo const& f) 
    : a(f.a) 
    , b(f.b) 
    , c(f.c) 
{} 



*/ 

// Now you can use all three methods and they work fine: 
public Foo(int a = 0, int b = 0, int c = 0) 
    : a(a) 
    , b(b) 
    , c(c) 
{} 

F f1;  // default construct no parameters: uses the three parameter version 
F f2(f1); // Copy constructed. Generated by the compiler. 
F f3(1,2,3); // Nomal constructor 
+0

En general, estoy en contra de usar valores predeterminados para los parámetros, si no, todas las permutaciones de cómo puede usarlo ahora tienen sentido, es decir, ahora tiene cuatro maneras de usar 'Foo (int, int, int)', que posiblemente no lo haga tener sentido. –