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

Why deleted copy constructor doesn't let to use other constructor with polymorphic type?

本文关键字:构造函数 多态 类型 其他 删除 复制 不允许 为什么      更新时间:2023-10-16

我想知道为什么这个程序不编译(在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实例显式转换为Action&,因为编译器抱怨尝试引用已删除的复制构造函数。是否有一些标准规则可以解释这种行为?

删除 a 函数不会将其从重载解析中删除。该函数仅定义为已删除。目的是在重载分辨率选择该功能时使程序格式不正确。

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

如何最好地处理它是值得商榷的。从理论上讲,您可以让副本c'tor进行类似的包装。但是,我对拥有一个不复制的副本c'tor感到困惑。你的磨坊可能非常。

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

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

现在,该类可以真正保持不可复制,并且客户端永远不需要自己转换它。如果他们将ActionDecorator传递给decorate,它将在构造实例之前绑定到Action引用。所以它甚至不会考虑复制 c'tor。

但是,该类必须是可移动的,以便在C++17之前工作。