2017-02-09 32 views
1

所以,我一直在尝试用静态类领域(尤其是那些不变),并让自己陷入到....这:该静态类字段在创建之前正在使用吗?

#include <iostream> 
#include <conio.h> 

class Test { 
public: 
    Test() { std::cout << "Constructing (Default CTOR)\n"; } 
    Test(int f) { std::cout << "Constructing (Int arg CTOR)\n"; } 

    void method() const { std::cout << "Already constructed and being used\n"; } 
}; 

class Stack { 
public: 
    // static const Test what{ 5 }; // - "element of type "const Test" can not have an initializer inside of a class" 
    // const Test ok{ 5 }; // now it can (?) 

    static const Test what; 

    Stack() { 
     what.method(); 
    } 

    // Stack() : what{5} {} // can't do that because "what" will be dependent on object creation (which is not how static class fields roll) 
}; 

Stack obj; 

const Test Stack::what{}; 

int main() 
{ 
    _getch(); 
    return 0; 
} 

输出:

Output

显然, static const Test whatStack之前被实际创建(?)。

后,我跑了另外一个测试:

#include <iostream> 
#include <conio.h> 

class Test { 
public: 
    int data; 

    Test() { std::cout << "CONSTRUCTING (Default CTOR)\n"; } // notice, value-initialization of 'data' has been removed 
    Test(int f) : data{ f } { std::cout << "CONSTRUCTING (Int arg CTOR)\n"; } 

    void method() const { std::cout << "ALREADY CONSTRUCTED AND BEING USED :)\n" << data << std::endl; } 
}; 

class Stack { 
public: 
    static const Test what; 

    Stack() { 
     what.method(); 
    } 
}; 

Stack obj; 

const Test Stack::what{ 5 }; 

int main() 
{ 
    obj.what.method(); 

    _getch(); 
    return 0; 
} 

在这段代码中,我希望能看到一些错误,但输出结束这样看:

Output 2

我对这里发生的事情有一些假设,但我不确定它们是否正确。所以,如果是的话,请纠正我。

这里是我的假设:

基本上,在节目的一开始创建静态变量(和值是初始化)和destoyed在节目的最后(实际上当你闭上你的.exe )。 在我的例子中,我有一个Stack类中的静态常量变量what,我认为它是在我的程序初始值初始化时创建的。这就是为什么它的data字段设置为0,我们可以使用它的方法。但我不认为这是正确的,因为它会输出Constructing (Default CTOR)到控制台中。所以我有点卡在那里...

我也不明白为什么我的第一个例子中的评论行是非法的。静态/常量类字段的哪些规则是否完全破坏?

如果您对我的示例中发生的事情有任何想法,请解释它。

感谢您的关注。

+0

我怀疑这与默认的构造函数实际上没有修改对象中的任何东西有关。如果将第二个默认构造函数更改为“:data {1}”,会发生什么? – Barmar

+0

@Barmar,什么都没有。输出仍然是一样的,没有错误。 –

+0

因为'#include '我无法编译你的代码。如果你坚持使用标准的C++,我可能会帮助你。 – nwp

回答

1

命名空间范围(即不在函数内部)的静态变量按源文件中其定义的顺序构造。此排序仅适用于相同源文件中的变量之间,而不适用于不同源文件之间。

因此obj始终在what之前构建。有限的事情可以通过具有构造函数但调用构造函数之前的对象来完成;并且调用成员函数不是其中之一(C++ 14 [basic.life] /5.2)。所以在Stack的构造函数中调用what.method()会导致未定义的行为。

+0

啊,我明白了。感谢您提供丰富的答案!所以,我的第二个exmaple的输出中的零应该是错误的:) –

相关问题