在Bjarne Stroustrup撰写的“C ++编程语言”一书中,作者说:
有时候,当你设计一个库时,有必要或者只是方便地发明一个带有构造函数和析构函数的类型,其唯一目的是初始化和清理。这样的类型只能使用一次:分配一个静态对象,以便调用构造函数和析构函数。例如:
class Zlib_init { Zlib_init() ; //get Zlib ready for use ~Zlib_init() ; //clean up after Zlib }; Class Zlib { static Zlib_init x; / /... };
不幸的是,不能保证这样的对象在第一次使用之前被初始化,并且在最后一次使用它之后被销毁在由单独编译的单元组成的程序中。
为什么作者将构造函数和析构函数保留为私有成员?
如果我们在由单独编译的单元组成的程序中使用它,为什么这个方法不起作用?
是否需要定义成员x
来调用构造函数Zlib_init()
和析构函数~Zlib_init()
?那么这种方法的用途是什么?
这是在本书的第10.4.9节。
答案 0 :(得分:8)
为什么作者将构造函数和析构函数保留为私有成员?
构造函数&析构函数private
似乎是一个错字
{class} {}}成员需要定义才能使用。为了定义静态成员static
,需要可以访问构造函数。如果不是链接器会抱怨未定义的引用。
<强> Online Sample 强>:
x
输出
class Zlib_init
{
Zlib_init() ; //get Zlib ready for use
~Zlib_init() ; //clean up after Zlib
public:
int j;
};
class Zlib
{
public:
static Zlib_init x;
};
Zlib_init Zlib::x;
int main()
{
Zlib::x.j = 10;
return 0;
}
如果我们在由单独编译的单元组成的程序中使用它,为什么这个方法不起作用?
如果您通过making the constructor and destructor public
或Zlib
a friend of class Zlib_init
修正了上述错字,则代码仍会面临另一个问题。
这个问题通常被称为C ++中的静态初始化Fiasco 。
好读:
[10.14] What's the "static initialization order fiasco"?
[10.17] How do I prevent the "static initialization order fiasco" for my static data members?
答案 1 :(得分:1)
为什么作者将构造函数和析构函数保留为私有成员?
我只是猜测,但我认为作者将声明剥离到了最低限度的必要条件以传达他的想法。虽然struct
而不是class
也可以起作用,但在他的书的其他地方,作者在这种情况下使用省略号(...)。所以我不确定。
如果我们在由单独编译的单元组成的程序中使用它,为什么这个方法不起作用?
静态对象的构造函数将在main
之前运行,所以如果你只在Zlib
调用的东西中使用main
,那么一切都运行良好。如果某个其他编译单元中的某个其他静态对象尝试在其构造函数中使用Zlib
,则会出现问题。无法保证这两个构造函数的执行顺序,因此您最终可能会尝试使用未初始化的Zlib
类。