5

为什么这个C++程序即使不构造类对象也能成功运行?让我们看看下面的代码:

#include<iostream>

using namespace std;

class Dopey
{
  public:
    Dopey() {cout << "Dopey\n";}
};

class Bashful
{
  public:
    Bashful() { cout << "BashFul\n";}
    void f() { cout << " f \n";}
    int i;
};

class Sneezy
{
  public:
    Sneezy(int i) {cout << "copy int \n";}
    Sneezy(Bashful d) { cout << "copy Bashful\n";}
    Sneezy(Bashful* d) {d->f();d->i=100;} //How could this be correct without    
                                              //  constructing d !!!!!!!!
    Sneezy();
};

class Snow_White
{
  public:
    Snow_White();
    Dopey dopey;
    Sneezy sneezy;
    Bashful bashful;
  private:
    int mumble;
};

Snow_White::Snow_White() : sneezy(&bashful)
{
    mumble = 2048;
}

int main()
{

    Snow_White s;

    return 0;
}

该程序可以成功运行,cout如下:

Dopey
f
BashFul

看看without constructing bashful,the f() could be invoked,为什么?当我将功能更改Snow_White::Snow_White()为以下内容时:

Snow_White::Snow_White() : sneezy(bashful)
{
    mumble = 2048;
}

它也runs successfully without constructing bashful,cout如下:

Dopey
copy Bashful
Bashful

任何解释将不胜感激!谢谢 !

4

3 回答 3

6

您的程序具有未定义的行为,因为您bashful在构建之前访问它。

于 2012-11-14T02:52:26.193 回答
2

您的问题与您的初始化列表有关。bashful 在打喷嚏之后声明。因此,在这段代码中:

Snow_White::Snow_White() : sneezy(&bashful)

bashul 还没有构建,因为根据白雪公主的声明,sneezy 必须先构建(是的,顺序很重要)。因此,sneezy的构造函数传入的参数指向了一个未初始化的对象。在这一点上,它起作用的原因是chris 与. 请记住,虽然这可行,但根据 C++ 标准,行为是未定义的,这意味着您不能也不能依赖它来工作

然而,真正的问题是 bashful 还没有被构建。

要解决这个问题,您需要更改 Snow_White 类的声明,以便 bashful 出现在 sneezy 之前:

class Snow_White
{
  public:
    Snow_White();
    Dopey dopey;
    Bashful bashful;
    Sneezy sneezy;
  private:
    int mumble;
};

避免这种事情发生的一种方法是始终按字母顺序保留您的声明和初始化列表。

另一种方法是从一开始就让你的班级小,所以这永远不是问题:)

于 2012-11-14T03:17:36.220 回答
0

The bashful member is being constructed as is shown by the inclusion of Bashful in the output. It is true that it is not constructed prior to the address of bashful being taken and passed to the other member's constructor.

There are specific rules as to the order in which member are initialized, but the order initialization or use in the constructor initialization list is not one of the factors in those rules.

于 2012-11-14T02:54:29.777 回答