C++ 中没有静态构造函数的理由是什么?

发布于 2024-10-22 01:14:07 字数 520 浏览 6 评论 0原文

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#)都有静态构造函数!

What is the rationale for not having static constructor in C++?

If it were allowed, we would be initializing all the static members in it, at one place in a very organized way, as:

//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");
    }
};

In the absense of static constructor, it's very difficult to have static vector, and populate it with values, as shown above. static constructor elegantly solves this problem. We could initialize static members in a very organized way.

So why doesn't' C++ have static constructor? After all, other languages (for example, C#) has static constructor!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

毅然前行 2024-10-29 01:14:08

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

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 之前,但不一定)

You could get by with putting your "static" members in their own class with their own constructor that performs their initialization:

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

    }
};

Your static data member is guaranteed to be initialized before you first try to access it. (Probably before main but not necessarily)

呆° 2024-10-29 01:14:08

静态意味着与对象解除关联的函数。由于只构造对象,因此静态构造函数为何有任何好处尚不清楚。

您始终可以将在静态块中构造的对象保存在静态范围内,但您将使用的构造函数仍将被声明为非静态。没有规则表明您不能从静态范围调用非静态方法。

最后,C++/C 定义程序的开始时间是进入 main 函数时。静态块在进入 main 函数之前调用,作为设置评估代码“环境”的一部分。如果您的环境要求完全控制设置和拆卸,那么很容易认为它实际上并不是某种环境固定装置,而是程序的继承过程组件。我知道最后一点是代码哲学(并且其基本原理可以有不同的解释),但是不应该在可执行文件正式开始将“完全控制”移交给所编写的代码“之前”放置关键代码由程序员。

Static implies a function that is disassociated with an object. Since only objects are constructed, it is not apparent why a static constructor would have any benefit.

You can always hold an object in a static scope which has been constructed in a static block, but the constructor you would use would still be declared as non-static. There's no rule that indicates you can't call a non-static method from a static scope.

Finally, C++ / C defines the start of a program to be when the main function is entered. Static blocks are called prior to the entry of the main function as part of setting up the "environment" of the evaluated code. If your environment dictates full control over the set-up and tear-down, then it's easy to argue that it's not really some environmental fixture as much as an inherit procedural component of the program. I know that the last bit is sort of code-philosophy (and that it's rationale could be interpreted differently), but one shouldn't put critical code "before" the official start of an executable's handing off "full control" to the code written by the programmer.

⒈起吃苦の倖褔 2024-10-29 01:14:07

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

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

//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;
  }
}

所以答案是,没有理由它不存在,至少不是技术上的。

Using the static initialization order problem as an excuse to not introduce this feature to the language is and always has been a matter of status quo - it wasn't introduced because it wasn't introduced and people keep thinking that initialization order was a reason not to introduce it, even if the order problem has a simple and very straightforward solution.

Initialization order, if people would have really wanted to tackle the problem, they would have had a very simple and straightforward solution:

//called before main()

int static_main() {

ClassFoo();
ClassBar();

}

with appropriate declarations:

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

class ClassBar {
  static int x;
  ClassBar() {
   x = ClassFoo::y+1;
  }
}

So the answer is, there is no reason it isn't there, at least not a technical one.

沉鱼一梦 2024-10-29 01:14:07

这对于 C++ 来说并没有真正的意义 - 类不是第一类对象(就像在 Java 中一样)。

(static|anything) 构造函数意味着某些东西被构造了——而 C++ 类不是被构造的,它们只是被构造了。

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

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

IMO 不需要另一种语法方式来实现此目的。

This doesn't really make sense for c++ - classes are not first class objects (like in e.g. java).

A (static|anything) constructor implies something is constructed - and c++ classes aren't constructed, they just are.

You can easily achieve the same effect though:

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

IMO there's just no need for one more syntactic way of doing this.

记忆で 2024-10-29 01:14:07

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

一旦您考虑到静态必须放置在一个(且仅一个)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 的定义中,那么您甚至可以将其作为嵌套类放在那里。您只需在定义静态变量的同一位置定义它的实例(并且在它们通过默认构造函数初始化之后,否则您当然无法push_back代码>任何东西)。

C# 的发明晚于 C++ 15-20 年,并且具有完全不同的构建模型。毫不奇怪,它提供了不同的功能,并且 C++ 中的某些功能没有 C# 中那么简单。

C++0x 添加了一个功能,可以更轻松地使用一些数据初始化向量,称为“初始化列表”

In which translation unit would the static objects be placed?

Once you account for the fact that statics have to be placed in one (and only one) TU, it's then not "very difficult" to go the rest of the way, and assign values to them in a function:

// .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;

If you really want the code for sample_init to appear in the definition of class sample, then you could even put it there as a nested class. You just have to define the instance of it in the same place you define the statics (and after they've been initialized via their default constructors, otherwise of course you can't push_back anything).

C# was invented 15-20 years after C++ and has a completely different build model. It's not all that surprising that it offers different features, and that some things are less simple in C++ than in C#.

C++0x adds a features to make it easier to initialize vectors with some data, called "initializer lists"

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文