繁体   English   中英

将参数传递给基类构造函数时成员的初始化

[英]Initialization of a member when passing parameters to a base class constructor

在下面的代码中,我将在创建基类时为未初始化的类成员分配一个值。 为什么这没有引起运行时错误?

class Foo {
public:
    Foo(std::string) {}
};

class Bar : public Foo {
public:
    Bar() : Foo(s = f()) {} // assigning to uninitialized class member

    void print() { 
        std::cout << s << std::endl; 
    }
    std::string f() {
        return "Some string";
    }

private:
    std::string s;
};

int main()
{
    Bar b;
    b.print();
    return 0;
}

但是将另一个成员添加到Bar类会在创建Foo类时产生错误:

Class Bar {

// same as above

private:
    std::string s;
    int a;        // adding another member
};

为什么会这样?

“运行时错误”? 分配给未初始化的成员时没有“运行时错误”。 在C ++中,在运行时无法检测到“未初始化”状态,这就是为什么无法以任何确定性方式(例如“运行时错误”)对其进行处理的原因。

当您执行此类操作时,您的代码会显示未定义的行为 这种不确定的行为会消失,这本身是不可预测的。 它很容易对完全不相关的因素敏感,例如在类中声明另一个成员。 这里的所有都是它的。

我试图调试您的代码。 看来,当您写:

Bar() : Foo(s = f()) {}

尚未正确创建s对象。 因为Foo()构造函数调用尚未完成。 基本上处于未定义状态。 因此,任何行为都是不确定的。 但是,此代码行为并非未定义:

Bar() : Foo(/*anything*/) {
        s = f();
    } 

因为构造函数调用完成。


注意:我在msvc11中测试

当f()执行时,Bar类未初始化,因此成员'a'没有值。 有趣的是,此代码在Visual Studio 2008中运行,但是无论如何这都不安全。

拉兹万

基类和类成员按声明顺序初始化(虚拟基类不同):

  • 基类(第一个)按声明顺序(例如,类X:A,B,C}
  • 按声明顺序排列的成员(例如int a; int b; int c;)

构造函数中初始化时的顺序不会更改。

在您的情况下,Foo未初始化,因此Bar及其成员-未定义的行为(在分配时有一些垃圾数据)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM