web-dev-qa-db-fra.com

Désactiver le constructeur de copie

J'ai un cours :

class SymbolIndexer {
protected:
  SymbolIndexer ( ) { }

public:
  static inline SymbolIndexer & GetUniqueInstance ( ) 
  { 
    static SymbolIndexer uniqueinstance_ ;
    return uniqueinstance_ ; 
  }
};

Comment devrais-je le modifier pour désactiver le code comme:

SymbolIndexer symbol_indexer_ = SymbolIndexer::GetUniqueInstance ( );

et n'autorise que du code comme:

SymbolIndexer & ref_symbol_indexer_ = SymbolIndexer::GetUniqueInstance ( );
151
Humble Debugger

Vous pouvez rendre le constructeur de copie privé et ne fournir aucune implémentation:

private:
    SymbolIndexer(const SymbolIndexer&);

Ou en C++ 11, l'interdire explicitement:

SymbolIndexer(const SymbolIndexer&) = delete;
254

Si l'héritage multiple ne vous dérange pas (ce n'est pas si mal, après tout), vous pouvez écrire une classe simple avec un constructeur de copie privée et un opérateur d'affectation, puis la sous-classer:

_class NonAssignable {
private:
    NonAssignable(NonAssignable const&);
    NonAssignable& operator=(NonAssignable const&);
public:
    NonAssignable() {}
};

class SymbolIndexer: public Indexer, public NonAssignable {
};
_

Pour GCC, cela donne le message d'erreur suivant:

_test.h: In copy constructor ‘SymbolIndexer::SymbolIndexer(const SymbolIndexer&)’:
test.h: error: ‘NonAssignable::NonAssignable(const NonAssignable&)’ is private
_

Je ne suis cependant pas sûr que cela fonctionne dans tous les compilateurs. Il y a un question connexe , mais sans réponse pour le moment.

UPD:

En C++ 11, vous pouvez également écrire NonAssignable class comme suit:

_class NonAssignable {
public:
    NonAssignable(NonAssignable const&) = delete;
    NonAssignable& operator=(NonAssignable const&) = delete;
    NonAssignable() {}
};
_

Le mot clé delete empêche les membres d'être construits par défaut. Ils ne peuvent donc plus être utilisés dans les membres construits par défaut d'une classe dérivée. Essayer d’affecter donne l’erreur suivante dans GCC:

_test.cpp: error: use of deleted function
          ‘SymbolIndexer& SymbolIndexer::operator=(const SymbolIndexer&)’
test.cpp: note: ‘SymbolIndexer& SymbolIndexer::operator=(const SymbolIndexer&)’
          is implicitly deleted because the default definition would
          be ill-formed:
_

UPD:

Boost a déjà une classe juste pour le même but, je suppose qu'elle est même implémentée de la même manière. La classe s'appelle boost::noncopyable et est destinée à être utilisée comme suit:

_#include <boost/core/noncopyable.hpp>

class SymbolIndexer: public Indexer, private boost::noncopyable {
};
_

Je vous recommande de vous en tenir à la solution Boost si la politique de votre projet le permet. Voir aussi une autre _boost::noncopyable_- question relative pour plus d'informations.

27
firegurafiku

Rendre SymbolIndexer( const SymbolIndexer& ) privé. Si vous attribuez une référence, vous ne copiez pas.

4
Aaron Klotz