2015-07-08 24 views
6

Pensavo in teoria che la risposta a questa domanda fosse sì.È possibile rendere una funzione derivata una classe derivata dichiarando privato costruttore/operatore di copia nella classe base?

Tuttavia, in pratica, il mio compilatore (VS2010) non sembra lamentarsi nella seguente situazione: Ho una classe di base astratta che fornisce un'interfaccia comune (senza avere membri di dati) e vari sottotitoli e sububercassi derivati ​​da esso.

class Base 
{ 
public: 
    Base() {} 
    virtual ~Base() {} 

    virtual void interfaceFunction1() = 0; 
    virtual void interfaceFunction2() = 0; 
private: 
    Base(const Base&);   // all derived classes should be uncopyable 
    Base& operator=(const Base&); 

    // no data members 
}; 

mio compilatore trovato senza problemi per implementare anche costruttori di copia completa in sub o subsubclasses.

Come posso essere sicuro che tutte le classi derivate da Base siano non copiabili?

edit: Se ho capito bene, questo è esattamente quello che Scott Meyers ha spiegato al punto 6 del Effective C++ (3a edizione, 2005), con la sua idea della classe Uncopyable (solo esteso qui per una classe di interfaccia completa). Qual è la differenza che fa funzionare la sua idea? (So ​​che eredita privatamente, ma questo non dovrebbe rappresentare un problema)

+0

Può essere aggiunto un membro fittizio di dati. –

+1

Hai testato altri compilatori? Anche presentare una classe derivata sarebbe bello;) (in realtà più qualcosa di simile a un esempio compilabile.) – luk32

+0

Qual è l'uso di una funzione pura non contrassegnata come virtuale? –

risposta

3

Ciò dovrebbe impedire al compilatore di generare un costruttore di copie per le classi derivate che non ne dichiarano esplicitamente. Tuttavia, nulla impedisce a una classe derivata di dichiarare esplicitamente un costruttore di copie che farà qualcos'altro che chiamare il costruttore di copie di Base.

Non c'è modo di assicurarsi che le classi derivate siano istantanee ma non copiabili.

+0

Potrebbe essere una soluzione rendere Base() privato? (ma poi dovrei ricorrere ai metodi di factory static, il che sembra un sacco di problemi solo per rendere queste classi non copiabili) –

+0

@TG_ No, non funzionerebbe. Se lasci * tutti * 'Base' costruttori' private', la classe derivata non sarà in grado di inizializzarsi affatto (non per copia, non per impostazione predefinita, non in altro modo).Se si lascia un costruttore 'Base' accessibile, la classe derivata può utilizzarla nel proprio copistocaster. – Angew

1

Piuttosto che dichiarare il costruttore/operatore di copia come privato dichiararli come cancellati. Dichiarare copia costruttore/operatore come privato non è la soluzione migliore per rendere le classi derivate non copiabili. Se si desidera che la classe di base sia completamente non copiabile, dichiarare il costruttore/operatore di copia come come d come copia può ancora avvenire all'interno delle funzioni membro di Base come membri privati ​​sono accessibili alle funzioni di quella classe. È possibile utilizzare la funzione di C++ 11 di cancellazione:

Base(const Base&) = delete; // copy constructor 
Base& operator=(const Base&) = delete; // copy-assignment operator 

Ma dichiarando costruttore di copia/operatore privato è anche bene finché si è consapevoli del fatto che la copia possa ancora avvenire all'interno delle funzioni membro della Base.

+1

rendendoli privati ​​e dichiarando come eliminati ha lo stesso effetto –

+0

@ BЈовић Non necessariamente, rendendoli privati ​​non garantisce che gli oggetti di quel tipo non siano copiabili. Se li dichiariamo come cancellati, nessuna copia potrà mai aver luogo. L'articolo 11 di Effective Modern C++ afferma che il codice presente nelle funzioni membro e amico non verrà compilato se tenta di utilizzare una funzione membro eliminata. Dichiararli come privati ​​significa che il codice all'interno delle funzioni membro e gli amici di quella particolare classe possono utilizzarli e il collegamento fallirà a causa della definizione della funzione mancante. –

+1

Un costruttore di copie predefinito creerà un nuovo oggetto di base e non tenterà di copiarlo. Pertanto, questo approccio non funzionerà, se la classe derivata utilizza il costruttore di copie predefinito e la classe derivata sarà copiabile, mentre la base non lo è. –