抽象类和移动语义

Abstract classes and move semantics

根据“五规则”,当我声明以下之一时:复制或移动操作或析构函数我必须编写所有它们,因为编译器不会为我生成它们(其中一些)。但是,如果我的 class (A) 派生自具有虚拟析构函数的抽象 class,这是否意味着 class A 中的析构函数将被视为 "user-defined"?因此,移动语义是否不适用于此 class A 的对象,因为编译器不会为我生成移动构造函数?

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

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

在[class.copy]中:

If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if
(9.1) — X does not have a user-declared copy constructor,
(9.2) — X does not have a user-declared copy assignment operator,
(9.3) — X does not have a user-declared move assignment operator, and
(9.4) — X does not have a user-declared destructor.
[ Note: When the move constructor is not implicitly declared or explicitly supplied, expressions that otherwise would have invoked the move constructor may instead invoke a copy constructor. —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
}