为什么删除的复制构造函数不允许使用其他多态类型的构造函数?

2024-03-09

我想知道为什么这个程序无法编译(在 msvc、gcc 和 clang 上有相同的行为):

#include <iostream>

using namespace std;

struct Action
{
    virtual void action()
    {
        cout << "Action::action()\n";
    }
};

struct ActionDecorator : Action
{
    ActionDecorator(const ActionDecorator&) = delete;
    ActionDecorator(Action & action) : origAction(action)
    {
    }

    void action() override
    {
        decoration();
        origAction.action();
    }

private:
    void decoration()
    {
        cout << "ActionDecorator::decoration()\n";
    }

    Action & origAction;
};

int main()
{
    Action action;
    ActionDecorator actionDecorator(action);
    ActionDecorator actionDecorator2(actionDecorator);
    actionDecorator2.action();
}

根据我的预期,删除的复制构造函数应该让其他ActionDecorator实例构造ActionDecorator,因为它是Action的多态类型。相反,我必须将 ActionDecorator 实例显式转换为 Action&,因为编译器抱怨尝试引用已删除的复制构造函数。是否有一些标准规则可以解释这种行为?


删除函数不会将其从重载决策中删除。功能只是defined已删除。目的是当重载决策选择时使程序格式错误该功能.

由于复制 c'tor 比您提供的特殊基类 c'tor 更匹配,因此如果您不进行强制转换,重载解析将始终选择它。

如何最好地处理它是有争议的。你可以理论上让复制者进行类似的包装。然而,我对拥有一个不能复制的复制器感到很矛盾。你的里程可能会很大。

我个人更喜欢的另一种选择是不按原样提供公共构造函数。相反,让客户通过常规命名函数创建装饰器。像这样的事情:

ActionDecorator decorate(Action& action) {
  return {action};
}

现在,该类确实可以保持不可复制,并且客户将永远不需要自己转换它。如果他们通过了ActionDecorator to decorate,它将绑定到Action构建实例之前参考。所以它甚至不会考虑复制者。

然而,该类必须是可移动的,这样才能在 C++17 之前工作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么删除的复制构造函数不允许使用其他多态类型的构造函数? 的相关文章

随机推荐