Почему конструктор Zlib_init закрыт в классе Zlib_init в книге Бьярна Страуструпа

В книге Бьярна Страуструпа "Язык программирования 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 книги.

2 ответа

Решение

Почему автор сохраняет конструктор и деструктор в качестве закрытых членов?

Конструктор и деструктор private кажется опечаткой.
Учебный класс static члены должны быть определены для того, чтобы вы могли их использовать. Для того, чтобы статический член 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;
}

Выход:

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     

И почему этот метод не будет работать, если мы будем использовать его в программе, состоящей из отдельно скомпилированных модулей?

Если вы исправите упомянутую выше опечатку, сделав конструктор и деструкторpublic или делая Zlib друг классаZlib_init код все еще сталкивается с другой проблемой.
Эта проблема широко известна как статическая инициализация Fiasco в C++.

Хорошо для чтения:

[10.14] Что такое "фиаско статического порядка инициализации"?
[10.17] Как предотвратить фиаско статического порядка инициализации для моих статических членов данных?

Почему автор сохраняет конструктор и деструктор в качестве закрытых членов?

Я только догадываюсь, но я предполагаю, что автор сократил декларацию до минимума, необходимого для передачи своей идеи. Хотя struct вместо class работал бы так же хорошо, и в других местах своей книги автор использует многоточие (…) в таких случаях. Так что я не уверен.

И почему этот метод не будет работать, если мы будем использовать его в программе, состоящей из отдельно скомпилированных модулей?

Конструктор статического объекта будет запущен раньше mainтак что если вы используете только Zlib в материале, вызванном из main, все работает хорошо. Проблемы начинаются, если какой-то другой статический объект в каком-либо другом модуле компиляции пытается использовать Zlib в своем конструкторе. Нет никаких гарантий относительно порядка выполнения этих двух конструкторов, так что вы можете получить код, пытающийся использовать неинициализированный код. Zlib учебный класс.

Другие вопросы по тегам