2011-10-05 17 views
12

Una delle pietre d'angolo di OOP è riutilizzare il codice anziché ripeterlo più e più volte. Pertanto, i tuoi progetti si accorciano e diventano più leggibili.Costruttori riutilizzabili C++

C++ offre tutti gli strumenti necessari per riutilizzare i metodi anziché ripetere il codice. Anche se per quanto riguarda i costruttori non so come riutilizzarli.

Sono non parlare del patrimonio o il modo di inviare un messaggio al padre. Sto parlando del riutilizzo del costruttore della classe stessa.

L'analogia nella JAVA è qualcosa di simile:

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; 
} 

La mia domanda è, c'è qualche syntaxis in C++ che ti permette di fare così?

risposta

8

This is possible with recently published C++11, ma nessun compilatore C++ implementa ancora questa funzionalità.

+0

che è stato portato un paio di volte nella lista dev di Clang. Per quanto ne so, è considerato a bassa priorità perché non è tanto un cambiamento di vita che lambda, per esempio. Ovviamente, se qualcuno lo ritenesse davvero utile, sia Clang che gcc sono open source :) –

+0

Questa risposta potrebbe utilizzare un aggiornamento. –

6

C++ 11 ha aggiunto la delega del costruttore e l'ereditarietà del costruttore. Avrai bisogno di ottenere un compilatore che lo supporti però.

Per ereditare i costruttori, è richiesto un dichiarazione using:

class Base { ... }; 

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

di delegare, utilizzare il ctor-inizializzatore, ma specificare un altro costruttore della stessa classe, invece di eventuali oggetti secondari (tutti base e gli oggetti secondari verranno inizializzate dal costruttore delegata 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 
    {} 
}; 

e perfetto inoltro può anche rivelarsi utile.

+1

Ora dovrebbe essere disponibile, forse dovrebbe essere la risposta accettata ... – moodboom

11

Altri hanno già risposto a C++ 11, ma per C++ 03 c'è una possibile soluzione: utilizzare una classe base con i necessari costruttori.

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) { } 
}; 

Naturalmente, è necessario considerare se vale la pena il boilerplate per i vostri scopi.

+2

+1 per indicare una soluzione con i compilatori esistenti. –

+1

+1 per scrivere quello che avevo deciso di scrivere, prima che decidessi. –

2

Il soultion generalmente accettata per i compilatori attuali è quello di fare questo:

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; 
} 
}; 

Anche se questo può sembrare più di uccidere in questo esempio, che è solo a causa della semplicità dell'esempio. In un'applicazione del mondo reale questo porterebbe benefici in termini di riduzione del codice ripetuto.

+0

Quale lingua è questa? – Johnsyweb

+0

Mi dispiace, java e C++ si confondono insieme a volte. Ho modificato il mio post in modo che sia interamente in C++ valido assumendo ora le funzioni getA(), getB(), getC() valide. –

+1

'this.a' non è valido e il costruttore di copie dovrebbe prendere const riferimento come argomento. –

1

OK C++ 11 copre ciò che ti serve.

Ma il vostro caso semplice è una soluzione facile:

/* 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

Sono generalmente contrario all'uso dei valori predefiniti per i parametri se non _all_ le diverse permutazioni di come puoi usarlo ora ha senso, cioè ora hai quattro modi per usare 'Foo (int, int, int)', che forse non ha senso. –