【问题标题】:deleted constructor inheritance删除构造函数继承
【发布时间】:2016-01-27 08:08:35
【问题描述】:

构造函数继承的要求之一是派生类不能有任何具有相同签名的构造函数。但是,我不确定删除的函数在这些规则下的行为方式。

class Foo
{
    public:
    Foo() = delete;
    Foo(const Foo& a_Foo) = delete;
    Foo(int a_Value) : m_Value(a_Value) {}

    private:
    int m_Value;
};

class Bar : public Foo
{
    public:
    using Foo::Foo;
    Bar() : Foo(7) {};
    Bar(const Bar& a_Bar) : Foo(12) {};
};
  • 被删除的构造函数是否会被继承?
  • 如果是这样,Bar()Foo() 具有相同的签名,这是否会使代码无效?
  • 您可能会争辩说Foo(const Foo& a_Foo)Bar(const Bar& a_Bar) 具有不同的签名。复制构造函数在构造函数继承下的行为如何?

【问题讨论】:

  • 一个默认/复制/移动构造函数永远不会被继承,您是在询问一般已删除的构造函数,还是只询问这三个?

标签: c++ c++11 inheritance constructor


【解决方案1】:

考虑以下示例:

class Symbol {
  public:
    Symbol() = delete;
    Symbol(char ch) : c{ch} {}
  private:
    char c;
    //
};


class Derived : Symbol {
  public:
  private:
    int i;
};


class NotDerived {
  public:
  private:
    int i;
};

以下行无法编译。您不能使用已删除的构造函数创建类的对象。大家都知道。

// Can't create an object because of deleted constructor.
Symbol sym;

但是,您可以使用重载的构造函数创建基类的对象:

// Parametrized constructor, this one is fine.
Symbol sym_char('a');

Derived 类使用: public 继承,继承了基类Symbol 的所有内容,包括已删除的构造函数。事实上,如果Symbol 类有一个已删除的构造函数,不允许您使用默认构造函数创建该类的对象,那么从逻辑上讲,Derived 类也应该禁止您使用已删除的构造函数创建该类的对象。

//  note: default constructor of 'Derived' is implicitly deleted because base class 'Symbol' has a deleted default constructor
//  The deleted consturctor is inherited from the base class.
Derived d;

Derived 类继承了 Symbol 类的所有方法,包括所有已删除的构造函数!

如果去掉继承语句,观察继承删除的构造函数消失了。不再有已删除的构造函数。现在默认编译器生成的默认构造函数又回来了,因为删除的构造函数并没有覆盖它。

// No deleted constructor: works
NotDerived nd;

NotDerived 类有一个编译器生成的默认构造函数,因为它没有从任何东西继承。 Derived 类没有默认构造函数,它有一个已删除的构造函数,因为它继承自一个具有已删除构造函数的类。

正如我们在上面的实验中看到的,是的,基类中的所有方法包括已删除的方法都会被继承到派生类中。这意味着是的,基类中的已删除构造函数确实会被继承到派生类中!

【讨论】:

    【解决方案2】:

    Foo 构造函数已删除,因此您不能定义使用已删除 Foo 构造函数的类 Bar 的构造函数。在那里谈论继承是没有意义的,因为你永远不能创建使用已删除的Foo 构造函数的Bar 类的对象。

    被删除的构造函数是否会被继承?

    没有。它们已被删除,没有可继承的内容。

    如果是这样,Bar() 和 Foo() 具有相同的签名,这是否会使 代码无效?

    默认构造函数不能被继承。

    你可以争辩说 Foo(const Foo& a_Foo) 和 Bar(const Bar& a_Bar) 有不同的签名。复制构造函数如何表现 构造函数继承?

    复制构造函数也不能被继承。

    【讨论】:

    • @PiotrSkotnicki 同意...正在考虑仅默认 ctr。待修复
    • @PiotrSkotnicki,我认为这可行,但在这种情况下,根本没有 Foo ctor。
    • @Gread.And.Powerful.Oz 我现在可以在 OP 的代码中看到一个,这就是我在编辑之前阅读问题的方式
    • 我使 Foo 可构造。该示例具体(本来是伪代码)不起作用的事实,并没有引起我的问​​题
    【解决方案3】:

    默认、复制和移动构造函数是继承的,继承构造函数也不能为派生类隐式声明复制或移动构造函数。此外,如果派生类中已经存在具有相同签名的构造函数,则继承构造函数声明本质上只是“跳过”基类构造函数。

    对于候选继承构造函数集中的每个非模板构造函数,而不是构造函数 没有参数或具有单个参数的复制/移动构造函数,构造函数是隐式的 用相同的构造函数声明,除非有一个用户声明的构造函数具有相同的 在使用声明出现或构造函数将是默认值的完整类中的签名, 复制或移动该类的构造函数。

    ([class.inhctor]/3)

    另外,如果相应的基类构造函数被删除,继承的构造函数也会被删除。

    这样声明的构造函数与X 中的相应构造函数具有相同的访问权限。如果 X 中的相应构造函数被删除 (8.4)。继承构造函数不得显式实例化 (14.7.2) 或显式特化 (14.7.3)。

    ([class.inhctor]/4)

    【讨论】:

      猜你喜欢
      • 2014-09-25
      • 1970-01-01
      • 1970-01-01
      • 2013-06-01
      • 2023-04-03
      • 2014-05-30
      相关资源
      最近更新 更多