fornito Questo può venire un po 'tardi, dopo altre risposte, ma io ancora fare un tentativo.
È può implementare questa sicurezza, e senza cambiare classi derivate. Tuttavia, è necessario modificare utilizzando di tutte queste classi, che potrebbe essere molto peggio, a seconda del proprio scenario. Se stai ancora progettando, questa potrebbe essere un'alternativa praticabile.
Fondamentalmente, è possibile applicare curiously recurring template pattern e immettere il codice di inizializzazione dopo che il costruttore è stato richiamato. Inoltre, se lo fai come ho scritto qui sotto, puoi anche proteggere load
da essere chiamato due volte.
struct Loader {
int get(int index) { return 0; }
};
struct Base {
virtual ~Base() {} // Note: don't forget this.
protected:
virtual void load(Loader &) = 0;
};
struct Derived : public Base {
int value;
protected:
void load(Loader &l) {
value = l.get(0);
}
};
template<typename T>
class Loaded : public T
{
public:
Loaded() {
Loader l; T::load(l);
}
};
int main (int, char **)
{
Loaded<Derived> derived;
}
Francamente, tuttavia, se possibile, considererei un progetto alternativo. Spostare il codice load
ai vostri costruttori e fornire il caricatore come un argomento di riferimento inadempiente come segue:
struct Derived : public Base {
Derived (Loader& loader = Loader()) { ... }
};
In questo modo, si evita completamente il problema.
Sommario: le scelte sono le seguenti:
- Se non si è limitata da vincoli esterni e non si ha una vasta base di codici a seconda questo, cambia il vostro disegno per qualcosa di più sicuro.
- Se si desidera mantenere
load
così com'è e non modificare troppo le classi ma si è disposti a pagare il prezzo di modifica di tutte le istanze, applicare CRTP come proposto sopra.
- Se si insiste per essere in gran parte retrocompatibili con il codice client esistente, sarà necessario modificare le classi per utilizzare un PIMPL come altri hanno suggerito o convivere con il problema esistente.
fonte
2010-10-20 22:39:02
Qual è il problema? Puoi chiamare un metodo virtuale puro. –
@Benoit: non in un costruttore. @Vargas: Probabilmente può essere progettato meglio, quindi non hai questa dipendenza. Ad esempio, perché 'load' è una funzione separata chiamata nel costruttore? Perché non lasciare che 'Derived' carichi i propri valori. – GManNickG
@Benoit: dal costruttore? !!! Si chiama comportamento non definito in C++ –