为什么删除的复制构造函数不允许使用多态类型的其他构造函数? [英] Why deleted copy constructor doesn't let to use other constructor with polymorphic type?

查看:176
本文介绍了为什么删除的复制构造函数不允许使用多态类型的其他构造函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道为什么该程序无法编译(msvc,gcc和clang上的行为相同):

I wonder why this program doesn't compile (the same behavior on msvc, gcc and 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&由于编译器抱怨尝试引用已删除的副本构造函数.有一些解释这种行为的标准规则吗?

According to my expectation, deleted copy constructor should let construct ActionDecorator by other ActionDecorator instance, as it is polymorphic type of Action. Instead I have to explicit cast ActionDecorator instance to Action& as compiler complains about attempting to reference a deleted copy constructor. Is there some standard rule which explains such behavior?

推荐答案

删除函数不会将其从重载解析中删除.该功能只是定义为已删除.目的是当重载解析选择那个函数时使程序格式错误.

Deleting a a function doesn't remove it from overload resolution. The function is merely defined as deleted. The purpose is to make the program ill-formed when overload resolution chooses that function.

由于副本c'tor比您提供的特殊基类c'tor更匹配,因此,如果不进行重载,则始终使用重载分辨率.

Since the copy c'tor is a better match than the special base class c'tor you provided, overload resolution will always pick it if you don't cast.

如何最好地处理它是有争议的.从理论上讲,您可以让副本进行类似的包装.但是,我对于拥有无法复制的复制人感到不安.您的年龄可能非常大.

How to best handle it is debatable. You could theoretically have the copy c'tor do a similar sort of wrapping. I'm torn about having a copy c'tor that doesn't copy, however. Your millage may very.

我个人比较满意的另一种选择是不按原样提供公共构造函数.而是让客户端通过常规的命名函数创建装饰器.像这样:

Another option, which I'm personally much more comfortable with, is to not provide public constructors as is. Instead, have clients create decorators via a regular named function. Something like this:

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

现在,该类可以真正保持不可复制的状态,并且客户将不再需要自己强制转换它.如果他们将ActionDecorator传递给decorate,它将在构造实例之前绑定到Action引用.因此,它甚至不会考虑副本c'tor.

Now the class can truly remain non-copyable, and clients will never need to cast it themselves. If they pass an ActionDecorator to decorate, it will bind to an Action reference prior to constructing the instance. So it won't even consider the copy c'tor.

该类必须是可移动的,这样才能在C ++ 17之前运行.

The class will have to be movable, for this to work prior to C++17, however.

这篇关于为什么删除的复制构造函数不允许使用多态类型的其他构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆