【问题标题】:What's the easiest way to emulate =delete in C++03 for restricting copy/assignment operations?在 C++03 中模拟 =delete 以限制复制/赋值操作的最简单方法是什么?
【发布时间】:2014-11-28 20:57:30
【问题描述】:

C++11 允许您使用“= delete”语法将隐式编译器定义的方法标记为禁止使用,从而解决了长期以来困扰我的问题。 Wikipedia for more info.

class Foo
{
public:
     Foo();
    ~Foo();

    // No copy
    Foo(Foo const &) = delete;
    Foo& operator=(Foo const &) = delete;
};

对于我不希望复制或分配的类的复制和赋值运算符总是很麻烦。将它们设为私有需要大量样板代码,然后通常存在没有默认构造函数的成员数据,需要一些手动操作才能使编译器对您不希望任何人调用的函数感到满意。

class Bar
{
public:
   explicit Bar(UniqueResourceID id): m_data(id) { }
   ~Bar();

protected:
   SomeHandle  m_data; // no default constructor

// all this crap to keep from being able to copy.  Do not use any of these!!
private:
   Bar() { } // ERROR: m_data has no default constructor
   static UniqueResourceID s_invalidID; // now I'm making the problem worse,
                                        // because I don't actually need this
                                        // for anything real, except to shut
                                        // up some errors.
   Bar(Bar const &o): m_data(s_invalidID) { }
   Bar& operator =(Bar const &o): { return *this; }
};

不幸的是,我必须使用的一些编译器不是 C++11 编译器,也不提供 =delete。处理这些的最好方法是什么? (请告诉我有比第二个代码 sn-p 更好的方法。)

【问题讨论】:

  • 让他们private
  • private decl 的Bar() {} 中删除{}。 IE。 Bar(); 。你只需要声明它,而不是实现它。适用于所有。如果您在这样做之后发现您的代码没有链接,那么您的朋友或class Bar 中的某些东西指的是您试图掩盖的东西。在这种情况下,修复错误的调用者。
  • 有些人认为派生自boost::noncopyable 或类似的一种更好的方法:它简洁且直接表达意图。另见:stackoverflow.com/q/7823990
  • @dyp Boost 并非总是在所有平台上都可用/理想,但这是一个好点。感谢您的建议。
  • @PhilippeChaintreuil 编写自己的程序非常简单:基本上与您当前所做的相同,但在一个单独的类中。类似class noncopyable { noncopyable(noncopyable const&); noncopyable& operator=(noncopyable const&); public: noncopyable() {} };

标签: c++ copy-constructor c++03 c++98


【解决方案1】:

您正在编写所有 额外的废话,因为您实际上是在定义 deleted 运算符的主体——我认为您不必这样做,而我所做的只是进行声明在任何地方都没有实现,就像这样;

class Bar
{
public:
   explicit Bar(UniqueResourceID id): m_data(id) { }
   ~Bar();

protected:
   SomeHandle  m_data; // no default constructor

private:
   Bar(); 
   Bar(Bar const &o);
   Bar& operator =(Bar const &o);
};

这并不比编写附加= delete 的方法更冗长。

编辑:您对

的定义
....
private:
   Bar() {}

实际上很危险,因为它允许从 Bar 内的其他方法调用运算符而不会生成任何错误(链接器或编译器)

【讨论】:

  • 可能应该提到的是,虽然这完全是正确的答案,但是当您尝试调用它们时(尤其是在类范围内)遇到的错误是不同的。尝试使用外部/受保护设置时会出现访问错误,并且在类范围内会出现未定义的符号错误。
  • 没错,但我不认为在 C++03 中有任何解决方法。
  • @MadScienceDreams 的声明就是为什么我要多做些废话。我宁愿立即被告知有人在不应该使用这些方法之一的地方使用这些方法,而不是仅仅收到链接错误。很多链接器只会说你有一个未定义的引用,但不会给你任何指示该引用到底在哪里。但是:很高兴知道我是否陷入困境,如果我感到懒惰,我可以跳过它。
  • @PhilippeChaintreuil -- 但只有当您从 within 栏访问操作员时,才会出现链接错误。您的 额外的废话 实际上很危险,因为 private: Bar() { } 将允许从 Bar 中调用默认构造函数,这与您想要的相反。
  • @PhilippeChaintreuil 是的,定义函数是完全错误的,因为我可以写静态void BARBAR(Bar& bar) {Bar b = bar;}。错误的无用之处是它们删除语法的原因,但 Soren 的回答是老成语。
猜你喜欢
  • 1970-01-01
  • 2017-03-29
  • 1970-01-01
  • 2011-04-18
  • 1970-01-01
  • 2021-12-09
  • 1970-01-01
  • 2011-10-06
  • 2010-09-08
相关资源
最近更新 更多