在 C++0x 中继承构造函数

Posted

技术标签:

【中文标题】在 C++0x 中继承构造函数【英文标题】:Inheriting constructors in C++0x 【发布时间】:2011-03-23 10:07:36 【问题描述】:

假设我在我们期望成为下一个 C++ 标准的代码中有以下代码:

int f(int x) 
 
  std::cout << x;
  return x * x; 


struct A

  A(int x) : m_x(x) 
  int m_x;
;

struct B : A

  using A::A;
  B() : m_y(f(m_x)) 
  int m_y;
;

int main()

  B(5);

这会调用 B 的默认构造函数并打印出 5 并设置 m_y = 25 吗?还是 B 的默认构造函数不会运行,而 m_y 未初始化?

如果是后者,不调用 B 默认构造函数的原因是什么?很明显,A(int) B 仅继承初始化 A,并使 B 处于不确定状态。为什么 C++ 会选择未定义的行为而不是简单地调用 B() 的默认构造函数?它在很大程度上违背了继承构造函数的目的。

编辑:

也许这应该被允许:

using A::A : m_y(...)  std::cout << "constructing..." << std::endl; ...; 

【问题讨论】:

m_y 将未初始化,通过使用 A::A,您将得到如下内容:B::B(int x) : A::m_x(x) 。或者什么:) C++ 实际上选择编译带有错误的代码,因为您没有为 A 提供默认构造函数。它不是未定义的行为 :) 【参考方案1】:

using A::A; 在派生类中隐式声明B(int)。就是这样。

程序的其余部分不应按预期工作。因为您使用B(5) 调用B(int),所以m_y 未初始化。

请参阅 Bjarne Stroustrup 网站上的此示例:

struct B1 
    B1(int)  
;

struct D1 : B1 
    using B1::B1; // implicitly declares D1(int)
    int x;
;

void test()

    D1 d(6);    // Oops: d.x is not initialized
    D1 e;       // error: D1 has no default constructor

http://www2.research.att.com/~bs/C++0xFAQ.html#inheriting

来自同一链接的另一个示例:

struct D1 : B1 
        using B1::B1;   // implicitly declares D1(int)
        int x0;   // note: x is initialized
    ;

    void test()
    
        D1 d(6);    // d.x is zero
    

【讨论】:

如果 D1 有一个默认构造函数,它会在运行“D1 d(6);”行时运行吗? 他的示例没有为 D1 声明默认构造函数。当然,无论“使用 B1:B1”如何,x 都不会被初始化。然而,我的示例声明了一个默认构造函数。 @Clinton:是的。但是在您的示例中未调用默认构造函数。所以不管你是否定义它,你调用隐式声明的构造函数,在你的例子中是B(int) @Nawaz:为什么?不调用默认构造函数的原因是什么?在 C++ 中的任何其他实例中,您都不能在不调用其构造函数的情况下创建对象。 +1 @Clinton:如果您考虑一下using B1::B1 对编译器的含义,可能会更容易理解。该构造被翻译(在这种特殊情况下)为D1( int __x ) : B1(__x) 。请注意,这并不意味着调用B1 构造函数,而是创建一个将调用B1 构造函数的D1 构造函数。该构造函数没有显式修改成员x,因为它是int 类型,这意味着它未初始化。除非按照最后的代码 sn-p,它使用声明中的初始化语法,在这种情况下它将被正确初始化。

以上是关于在 C++0x 中继承构造函数的主要内容,如果未能解决你的问题,请参考以下文章

C++中继承类的构造函数

为啥我不能访问派生构造函数的成员初始化列表中继承的受保护字段?

ES5和ES6中继承的不同之处

JavaScript中继承的实现方式

JavaScript中继承的实现方式

javascript中6中继承方式