c++ - 隐式删除子项时继承父项赋值运算符

标签 c++ inheritance c++11 move using-declaration

在 GCC 4.6 中,即使子项的赋值运算符由于 move 构造函数而被隐式删除,也可以继承父项的赋值运算符。在更高版本的 GCC(以及 Clang)中,这不再是可能的。让子类使用父类的赋值运算符的正确方法是什么?

struct A
{
  A & operator=(A const & other) = default;
};

struct B : public A
{
  B() {}
  B(B && other) {}

  using A::operator=;
};

int main()
{
  B b1, b2;
  b1 = b2; // error: use of deleted function because B's operator= is implicitly deleted due to move constructor
  return 0;
}

最佳答案

被删除的函数仍然声明,只有定义被删除。在您的类定义中扩展它:

struct B : A {
   using A::operator=;               // A& operator=(const A&)
   B& operator=(const B&) = delete;
};

此时,您可以注意到派生类型中有两个 operator= 声明,第一个(通过 using-declaration) 采用 const A& 参数,而第二个采用 const B& 并且被删除

当您稍后尝试作业时:

B b1, b2;
b1 = b2;

两个声明都被编译器看到,第二个是更好的匹配。因为它被标记为已删除,所以您会收到错误消息。另一方面,如果您分配了一个 A 对象,它将按预期工作:

B b1, b2;
b1 = static_cast<A&>(b2); // works, BUT...

这种方法的问题在于它只复制了可能不是您想要的基础子对象。如果您只想要与编译器生成赋值时相同的行为,您需要请求它:

struct B : A {
   // ...
   B& operator=(const B&) = default;
};

关于c++ - 隐式删除子项时继承父项赋值运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15752650/

相关文章:

c++ - 通过隐式转换返回时是否需要复制构造函数?

c# - 建模 "I' m a * 但我也是一个 **”

python - 在Python中确定一个合适的子类来存储特定类型的数据

java - 使用抽象方法而不是字段

c++ - 在现代 C++ 中比较 double/float 是否相等的现代实践

c++ - 没有从 long unsigned int 到 long unsigned int& 的转换

c++ - 通过引用捕获异常

c++ - 如何在C++中将多个文件包装到同一个命名空间中

c++ - 线程 sleep VS 等待条件

c++ - 为什么构造函数/析构函数被调用一次?