0

考虑一个防止复制构造和复制分配的基类,如下所示:

class NonCopyable {
    public:
        NonCopyable() = default;
        ~NonCopyable() = default;

        NonCopyable(NonCopyable const&)                 = delete;
        NonCopyable& operator=(NonCopyable const&)      = delete;
};

我们的开发人员现在可以包含这个类,并使用它来禁用继承类的复制,如下所示:

class CopyTest : public NonCopyable {
    public:
        CopyTest() {
            std::cout << "copy test created" << std::endl;
        }

        ~CopyTest() {
            std::cout << "copy test deleted" << std::endl;
        }
};

当我尝试使用CopyTest该类时:

CopyTest ct, ct1(ct);

或者

CopyTest ct;
CopyTest ct1 = ct2;

编译器发出错误:(use of deleted function xxx其中 xxx 是我删除的复制 ctor 或复制运算符)

然后,如果我想要std::move一个CopyTest对象:

CopyTest ct;
CopyTest ct1 = std::move(ct);

编译器发出相同的错误(使用已删除的函数 xxx - 其中 xxx 仍然是我的复制 ctor 或赋值运算符)。

如果我提醒正确,那是因为开发人员没有定义正确的移动 ctor/赋值运算符。

是否可以强制编译器告诉CopyTest类的开发人员移动错误在这里,因为他没有定义正确的移动 ctor/赋值运算符,而不是因为复制 ctor/赋值运算符在基类上被删除?

平台 :

Debian 9

海合会 6.3.0

编译标志:

-fpermissive -ggdb -std=c++11

4

2 回答 2

2

添加

    NonCopyable(NonCopyable &&)                 = delete;
    NonCopyable& operator=(NonCopyable &&)      = delete;

现在抱怨基类移动ctor被删除。

于 2018-12-12T19:55:19.420 回答
0

NonCopyable正式地说,隐式生成的移动 ctor/assignment 在基类本身中被定义为“已删除” 。“已删除”的移动 ctor/assignment 只是被重载决议忽略(而不是在严格意义上被删除)。由于NonCopyable不可复制且不可移动,因此任何子类都将其隐式(并且=默认)复制和移动操作定义为已删除。

在严格的 iso c++ 下,您的设计具有所需的语义,但不幸的是,大多数编译器并未严格执行所谓的五规则,而仅执行隐式删除规则的子集。例如,让用户为类声明析构函数意味着所有复制和移动操作的隐式(和=默认)定义将被删除,但我不知道编译器在隐式编译时无法编译或发出警告声明的复制构造函数将是用于此类的 ODR。

我遇到了这个错误报告https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58407#c16。它表明编译器可能会开始强制执行或警告五项违规规则。

于 2018-12-13T00:05:35.220 回答