抽象类和移动语义

时间:2015-04-23 21:03:05

标签: c++ c++11 move-semantics

根据“Five of Rule”,当我声明其中一个:复制或移动操作或析构函数时,我必须编写所有这些,因为编译器不会为我生成它们(其中一些)。但是如果我的类(A)派生自带有虚拟析构函数的抽象类,这是否意味着类A中的析构函数将被视为"用户定义"?因此,移动语义不适用于此类A的对象,因为编译器不会为我生成移动构造函数吗?

struct Interface {
    virtual void myFunction() = 0;
    virtual ~Interface() {};
};

struct A : public Interface {
    void myFunction() override {};
};

1 个答案:

答案 0 :(得分:11)

在[class.copy]中:

  

如果类X的定义没有显式声明一个移动构造函数,那么将隐式声明一个   当且仅当如此时违约   (9.1) - X没有用户声明的拷贝构造函数,
  (9.2) - X没有用户声明的复制赋值运算符,
  (9.3) - X没有用户声明的移动赋值运算符,和
  (9.4) - X没有用户声明的析构函数。
   [注意:当没有隐式声明或显式提供移动构造函数时,否则表达式   会调用移动构造函数可能会调用复制构造函数。 -end note]

Interface确实有一个用户声明的析构函数,因此Interface的移动构造函数不会被隐式声明为默认值。但是A并不适合任何这些项目符号 - 因此具有默认的隐式移动构造函数。根据说明,A(A&& )只会复制Interface部分。我们可以通过向InterfaceA添加成员来验证这一点:

#include <iostream>

template <char c>
struct Obj {
    Obj() { std::cout << "default ctor" << c << "\n"; }  
    Obj(const Obj&) { std::cout << "copy ctor" << c << "\n"; }
    Obj(Obj&&) { std::cout << "move ctor" << c << "\n"; }
};

struct Interface {
    virtual void myFunction() = 0;
    virtual ~Interface() {};

    Obj<'I'> base;
};

struct A : public Interface {
    void myFunction() override {};

    Obj<'A'> derived;
};

int main() {
    A a1;                      // default I, default A
    std::cout << "---\n";
    A a2(std::move(a1));       // copy I, move A
    std::cout << "---\n";
    A a3(a2);                  // copy I, copy A
}