在C++中没有静态构造函数的基本原理是什么?

Naw*_*waz 29 c++ language-features constructor language-design static-constructor

在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");
    }
};
Run Code Online (Sandbox Code Playgroud)

在静态构造函数的缺失中,很难有静态向量,并用值填充它,如上所示.静态构造函数优雅地解决了这个问题.我们可以以非常有组织的方式初始化静态成员.

那么为什么'C++没有静态构造函数?毕竟,其他语言(例如,C#)具有静态构造函数!

lur*_*her 20

使用静态初始化顺序问题作为不向该语言引入此功能的借口一直是现状问题 - 它没有被引入,因为它没有被引入并且人们一直认为初始化顺序不是原因引入它,即使订单问题有一个简单而直接的解决方案.

初始化顺序,如果人们真的想要解决问题,他们会有一个非常简单直接的解决方案:

//called before main()

int static_main() {

ClassFoo();
ClassBar();

}
Run Code Online (Sandbox Code Playgroud)

适当的声明:

class ClassFoo {
 static int y;
  ClassFoo() {
   y = 1;
  }
}

class ClassBar {
  static int x;
  ClassBar() {
   x = ClassFoo::y+1;
  }
}
Run Code Online (Sandbox Code Playgroud)

所以答案是,没有理由不存在,至少不是技术问题.

  • 大多数库在main()之前需要一些初始化代码才能使用它们; 即使其他库使用了库,通常只保证初始化只发生一次的唯一方法是将这种初始化委托给全局main().具有指定静态构造函数的语法并不能神奇地解决这个问题,但会使初始化要求明确 - 您忘记调用静态构造函数了吗?嘿,编译器会给出一个明智的警告 (5认同)
  • 就像主要一样; 图书馆不应该有一个 (2认同)
  • +1 说这个 *“使用静态初始化顺序问题作为不向语言引入此功能的借口是并且一直是现状问题 - 没有引入它是因为它没有引入并且人们一直在思考初始化顺序是不引入它的一个原因,即使顺序问题有一个简单且非常直接的问题”*。 (2认同)

Eri*_*rik 13

这对c ++来说没有意义 - 类不是第一类对象(比如java).

一个(static | anything)构造函数意味着构造了一些东西 - 并且没有构造c ++类,它们就是这样.

您可以轻松实现相同的效果:

//.h
struct Foo {
  static std::vector<std::string> strings;
};
//.cpp
std::vector<std::string> Foo::strings(createStrings());
Run Code Online (Sandbox Code Playgroud)

IMO没有必要再采用一种语法方式.

  • @Nawaz:我宁愿认为他们当时并不知道更好,或者无法想办法让它向后兼容. (5认同)
  • @Nawaz:C++从来都不知道它的美妙和可理解的语法;) (4认同)

Ste*_*sop 6

静态对象放在哪个翻译单元中?

一旦你考虑到必须将静态放在一个(并且只有一个)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;
Run Code Online (Sandbox Code Playgroud)

如果你真的希望代码sample_init出现在类的定义中sample,那么你甚至可以把它作为嵌套类放在那里.你只需要在你定义静态的同一个地方定义它的实例(它们通过它们的默认构造函数初始化之后,当然你不能做push_back任何事情).

C#是在C++之后15 - 20年发明的,并且具有完全不同的构建模型.它提供不同的功能并不令人惊讶,并且C++中的某些东西不像C#那么简单.

C++ 0x添加了一些功能,可以更容易地使用一些数据初始化向量,称为"初始化列表"


Dav*_*ger 5

你可以通过将你的“静态”成员放在他们自己的类中,并使用他们自己的构造函数来执行它们的初始化:

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()
    {

    }
};
Run Code Online (Sandbox Code Playgroud)

data在您第一次尝试访问它之前,您的静态成员保证已被初始化。(可能在 main 之前但不一定)