我有一门课:

class SymbolIndexer {
protected:
  SymbolIndexer ( ) { }

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

我应该如何修改它来禁用如下代码:

SymbolIndexer symbol_indexer_ = SymbolIndexer::GetUniqueInstance ( );

并且只允许这样的代码:

SymbolIndexer & ref_symbol_indexer_ = SymbolIndexer::GetUniqueInstance ( );

当前回答

你可以将复制构造函数设为私有,不提供任何实现:

private:
    SymbolIndexer(const SymbolIndexer&);

或者在c++ 11中,显式禁止它:

SymbolIndexer(const SymbolIndexer&) = delete;

其他回答

使SymbolIndexer(const SymbolIndexer&)为私有。如果你给一个引用赋值,你就不是在复制。

你可以将复制构造函数设为私有,不提供任何实现:

private:
    SymbolIndexer(const SymbolIndexer&);

或者在c++ 11中,显式禁止它:

SymbolIndexer(const SymbolIndexer&) = delete;

如果你不介意多重继承(毕竟它也没那么糟糕),你可以写一个简单的带有私有复制构造函数和赋值操作符的类,并额外子类化它:

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

class SymbolIndexer: public Indexer, public NonAssignable {
};

对于GCC,这将给出以下错误消息:

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

不过,我不太确定这是否适用于每个编译器。还有一个相关的问题,但还没有答案。

UPD:

在c++ 11中,你也可以这样写NonAssignable类:

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

delete关键字防止成员被默认构造,因此不能在派生类的默认构造成员中进一步使用它们。在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已经有一个类是为了同样的目的,我猜它甚至是以类似的方式实现的。这个类被称为boost::noncopyable,它的用途如下:

#include <boost/core/noncopyable.hpp>

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

如果你的项目策略允许的话,我建议你坚持使用Boost的解决方案。有关更多信息,请参见另一个boost::不可复制相关问题。