C++ 中没有静态构造函数的理由是什么?
如果允许,我们将以一种非常有组织的方式在一个地方初始化其中的所有静态成员,如下所示:
//illegal C++
class sample
{
public:
static int some_integer;
static std::vector<std::string> strings;
//illegal constructor!
static sample()
{
some_integer = 100;
strings.push_back("stack");
strings.push_back("overflow");
}
};
在没有静态构造函数的情况下,很难拥有静态向量并用值填充它,如上所示。静态构造函数优雅地解决了这个问题。我们可以以一种非常有组织的方式初始化静态成员。
那么为什么 C++ 没有静态构造函数呢?毕竟其他语言(例如C#)都有静态构造函数!
使用静态初始化顺序问题作为不将此功能引入该语言的借口一直是现状问题 - 它没有被引入是因为它没有被引入并且人们一直认为初始化顺序是一个原因不介绍了,即使订单问题有一个简单且非常直接的解决方案。
初始化顺序,如果人们真的想解决这个问题,他们会有一个非常简单直接的解决方案:
//called before main()
int static_main() {
ClassFoo();
ClassBar();
}
带有适当的声明:
class ClassFoo {
static int y;
ClassFoo() {
y = 1;
}
}
class ClassBar {
static int x;
ClassBar() {
x = ClassFoo::y+1;
}
}
所以答案是,没有理由不存在,至少不是技术原因。
这对于 C++ 来说并没有什么意义——类不是第一类对象(就像在 java 中一样)。
(静态|任何)构造函数意味着某些东西被构造了——而 C++ 类不是被构造的,它们只是被构造了。
您可以轻松实现相同的效果:
//.h
struct Foo {
static std::vector<std::string> strings;
};
//.cpp
std::vector<std::string> Foo::strings(createStrings());
IMO 不需要再一种语法方式来做到这一点。
静态对象将被放置在哪个翻译单元中?
一旦考虑到静力学必须放置在一个(且只有一个)TU 中这一事实,那么完成其余部分并在函数中为它们赋值就不是“非常困难”了:
// .h
class sample
{
public:
static int some_integer;
static std::vector<std::string> strings;
};
//.cpp
// we'd need this anyway
int sample::some_integer;
std::vector<std::string> sample::strings;
// add this for complex setup
struct sample_init {
sample_init() {
sample::some_integer = 100;
sample::strings.push_back("stack");
sample::strings.push_back("overflow");
}
} x;
如果您确实希望
sample_init
的代码出现在类 sample
的定义中,那么您甚至可以将其作为嵌套类放在那里。您只需在定义静态的同一位置定义它的实例(并且after它们已通过默认构造函数初始化,否则当然您不能push_back
任何东西)。
C# 的发明晚于 C++ 15-20 年,并且具有完全不同的构建模型。毫不奇怪,它提供了不同的功能,而且 C++ 中的某些事情没有 C# 中那么简单。
C++0x 添加了一个功能,可以更轻松地使用一些数据初始化向量,称为“初始化列表”
您可以将“静态”成员放在自己的类中,并使用自己的构造函数来执行初始化:
class StaticData
{
int some_integer;
std::vector<std::string> strings;
public:
StaticData()
{
some_integer = 100;
strings.push_back("stack");
strings.push_back("overflow");
}
}
class sample
{
static StaticData data;
public:
sample()
{
}
};
您的静态
data
成员保证在您第一次尝试访问它之前被初始化。 (可能在 main 之前,但不一定)
静态意味着与对象无关的函数。由于仅构造对象,因此静态构造函数为何有任何好处尚不清楚。
您始终可以将在静态块中构造的对象保存在静态范围内,但您将使用的构造函数仍将被声明为非静态。没有规则表明您不能从静态范围调用非静态方法。
最后,C++ / C 定义程序的开始时间是进入
main
函数时。静态块在进入 main
函数之前调用,作为设置评估代码“环境”的一部分。如果您的环境要求完全控制设置和拆卸,那么很容易认为它实际上并不是某种环境固定装置,而是程序的继承过程组件。我知道最后一点是代码哲学(并且其基本原理可以有不同的解释),但是不应该在可执行文件正式开始将“完全控制”移交给所编写的代码“之前”放置关键代码由程序员。
除了其他答案之外,我认为这个功能是需要的。在我们使用静态成员或创建对象之前,即在使用类之前,必须调用静态构造函数。