【问题标题】:Why are the constructor Zlib_init kept private in class Zlib_init in the book by Bjarne Stroustrup为什么构造函数 Zlib_init 在 Bjarne Stroustrup 的书中的类 Zlib_init 中保持私有
【发布时间】:2012-10-05 05:14:32
【问题描述】:

在 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 节中。

【问题讨论】:

  • 无法编译 - 有多种原因
  • 这似乎比工作代码的实际演示更具说明性......

标签: c++ private-constructor


【解决方案1】:

为什么作者将构造函数和析构函数保留为私有成员?

private 的构造函数和析构函数似乎是一个错字。
static 类的成员需要定义,您才能使用它们。为了定义静态成员x,构造函数需要可访问。如果不是,链接器将抱怨未定义的引用。

Online Sample

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

输出:

prog.cpp:3: error: ‘Zlib_init::Zlib_init()’ is private     
prog.cpp:14: error: within this context      
prog.cpp: In static member function ‘static void Zlib::__static_initialization_and_destruction_0(int, int)’:     
prog.cpp:4: error: ‘Zlib_init::~Zlib_init()’ is private     
prog.cpp:14: error: within this context     

如果我们在由单独编译的单元组成的程序中使用它,为什么这个方法不起作用?

如果您通过making the constructor and destructor public 或通过使Zlib a friend of class Zlib_init 修复上面提到的错字,代码仍然面临另一个问题。
该问题在 C++ 中被普遍称为 Static Initialization 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?

【讨论】:

  • 感谢您的回复以及有关静态初始化惨败的其他信息..
  • B.Stroustrup 的书籍和文章中不时出现错别字。我猜,这是他用心写的代码。没时间测试。
【解决方案2】:

为什么作者将构造函数和析构函数保留为私有成员?

我只是猜测,但我认为作者将声明剥离到了传达他的想法所必需的最低限度。尽管struct 而不是class 也可以,但在他书中的其他地方,作者在这种情况下使用了省略号(...)。所以我不确定。

如果我们在由单独编译的单元组成的程序中使用这种方法,为什么它不起作用?

静态对象的构造函数将在main 之前运行,所以如果你只在从main 调用的东西中使用Zlib,一切正常。如果某个其他编译单元中的某个其他静态对象尝试在其构造函数中使用Zlib,那么问题就开始了。无法保证这两个构造函数的执行顺序,因此您可能会遇到一些尝试使用未初始化的 Zlib 类的代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-16
    相关资源
    最近更新 更多