Wyłącz Konstruktor kopiujący

Mam klasę:

class SymbolIndexer {
protected:
  SymbolIndexer ( ) { }

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

Jak mam go zmodyfikować, aby wyłączyć kod jak:

SymbolIndexer symbol_indexer_ = SymbolIndexer::GetUniqueInstance ( );

I Zezwalaj tylko na kod taki jak:

SymbolIndexer & ref_symbol_indexer_ = SymbolIndexer::GetUniqueInstance ( );
Author: Humble Debugger, 2011-05-21

3 answers

Możesz uczynić Konstruktor kopiujący prywatnym i nie dostarczyć żadnej implementacji:

private:
    SymbolIndexer(const SymbolIndexer&);

Lub w C++11 wyraźnie zabronić:

SymbolIndexer(const SymbolIndexer&) = delete;
 232
Author: R. Martinho Fernandes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-10 13:56:01

Jeśli nie masz nic przeciwko wielokrotnemu dziedziczeniu (w końcu nie jest tak źle), możesz napisać prostą klasę z prywatnym konstruktorem kopiującym i operatorem przypisania i dodatkowo podklasować ją:

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

class SymbolIndexer: public Indexer, public NonAssignable {
};

Dla GCC daje to następujący komunikat o błędzie:

test.h: In copy constructor ‘SymbolIndexer::SymbolIndexer(const SymbolIndexer&)’:
test.h: error: ‘NonAssignable::NonAssignable(const NonAssignable&)’ is private
Nie jestem jednak pewien, czy to zadziała w każdym kompilatorze. Istnieje podobne pytanie , ale bez odpowiedzi jeszcze.

Upd:

W C++11 Możesz również napisać NonAssignable klasę jako następuje:

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

Słowo kluczowe delete zapobiega konstruowaniu elementów składowych jako domyślnych, więc nie mogą być dalej używane w składach składowych klasy pochodnej. Próba przypisania powoduje następujący błąd w 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 ma już klasę tylko do tego samego celu, myślę, że jest nawet zaimplementowana w podobny sposób. Klasa nazywa się boost::noncopyable i ma być stosowany w następujący sposób:

#include <boost/core/noncopyable.hpp>

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

Polecam trzymać do rozwiązania Boost, jeśli polityka projektu na to pozwala. Zobacz też inne boost::noncopyable-podobne pytanie aby uzyskać więcej informacji.

 21
Author: firegurafiku,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:25:51

Make SymbolIndexer( const SymbolIndexer& ) private. Jeśli przypisujesz do referencji, Nie kopiujesz.

 4
Author: Aaron Klotz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-20 20:16:29