此静态 class 字段在创建之前已被使用?
This static class field is being used before it's been created?
所以,我一直在试验静态 class 字段(尤其是常量字段),并让自己陷入......这个:
#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;
}
输出:
显然,Stack
中的 static const Test what
在实际创建之前就已经被使用了(?)。
之后我 运行 另一个测试:
#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;
}
在此代码中,我希望看到某种错误,但输出结果如下所示:
我对这里发生的事情有一些假设,但我不确定它们是否正确。所以,如果他们是,请纠正我。
这是我的假设:
基本上,静态变量是在程序开始时创建的(并且是值初始化的)并在程序结束时销毁(当您实际关闭 .exe 时)。
在我的示例中,我在 class Stack
中有一个静态常量变量 what
,我认为它是在我的程序值初始化开始时创建的。这就是为什么它的 data
字段设置为 0 并且我们可以使用它的方法。但我认为这是不正确的,因为它会将 Constructing (Default CTOR)
输出到控制台。所以我有点卡在那里...
我也不明白为什么我第一个例子中的注释行是非法的。 static/constant class 字段的规则究竟是什么?
如果您对我的示例中发生的事情有任何想法,请解释一下。
感谢您的关注。
命名空间范围内的静态变量(即不在函数内)是按照它们在源文件中定义的顺序构造的。此排序仅适用于同一源文件中的变量之间,不适用于不同源文件之间。
所以obj
总是在what
之前构造。对于具有构造函数但在调用构造函数之前的对象,可以做的事情有限;调用成员函数不是其中之一 (C++14 [basic.life]/5.2)。所以在 Stack
的构造函数中调用 what.method()
会导致未定义的行为。
所以,我一直在试验静态 class 字段(尤其是常量字段),并让自己陷入......这个:
#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;
}
输出:
显然,Stack
中的 static const Test what
在实际创建之前就已经被使用了(?)。
之后我 运行 另一个测试:
#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;
}
在此代码中,我希望看到某种错误,但输出结果如下所示:
我对这里发生的事情有一些假设,但我不确定它们是否正确。所以,如果他们是,请纠正我。
这是我的假设:
基本上,静态变量是在程序开始时创建的(并且是值初始化的)并在程序结束时销毁(当您实际关闭 .exe 时)。
在我的示例中,我在 class Stack
中有一个静态常量变量 what
,我认为它是在我的程序值初始化开始时创建的。这就是为什么它的 data
字段设置为 0 并且我们可以使用它的方法。但我认为这是不正确的,因为它会将 Constructing (Default CTOR)
输出到控制台。所以我有点卡在那里...
我也不明白为什么我第一个例子中的注释行是非法的。 static/constant class 字段的规则究竟是什么?
如果您对我的示例中发生的事情有任何想法,请解释一下。
感谢您的关注。
命名空间范围内的静态变量(即不在函数内)是按照它们在源文件中定义的顺序构造的。此排序仅适用于同一源文件中的变量之间,不适用于不同源文件之间。
所以obj
总是在what
之前构造。对于具有构造函数但在调用构造函数之前的对象,可以做的事情有限;调用成员函数不是其中之一 (C++14 [basic.life]/5.2)。所以在 Stack
的构造函数中调用 what.method()
会导致未定义的行为。