我想知道为什么这个程序无法编译(在 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(使用前将#替换为@)