да нет: да он вызывается дважды, а нет вызывается для двух разных объектов.
Допустим, у вас есть
// A.cpp
#include "datafile.h"
...
и
// B.cpp
#include "datafile.h"
...
из-за #include A.cpp и B.cpp будут иметь локальную и независимую копию dfinitializer
.
datafile.cpp имеет в свою очередь nifty_counter
(лучше определить ее с помощью начальной0 value ... static int nifty_counter = 0;
) и CDatafile :: mSome (инициализируется на уровне файла).
То, что делает CDataFileInitializer
ctor, назначается уже инициализированному mSome
временному CSomeClass (), которыйсоздается и уничтожается на лету.
Все, что на самом деле является неправильной реализацией, делает правильные вещи только потому, что CDataFile может быть назначен.
Если проблема заключается только в инициализации статического члена данныхвсе, что вам нужно сделать, это убедиться, что что-то в модуле, содержащем определение статического члена (примечание: определение, а не объявление), вызывается другими, что вызывает некоторый побочный эффект в модуле (просто чтобы избежать оптимизации)
так что ... пустьПопробуйте лучший трюк
//some.h
#ifndef SOME_H_INCLUDED
#define SOME_H_INCLUDED
#include<iostream>
class CSome
{
public:
CSome() { std::cout << "CSome["<<this<<"] default created" << std::endl; }
CSome(const CSome& s) { std::cout << "CSome["<<this<<"] created from ["<<&s<<"]" << std::endl; }
CSome& operator=(const CSome& s) { std::cout << "CSome["<<this<<"] assigned from ["<<&s<<"]" << std::endl; return *this; }
CSome(CSome&& s) { std::cout << "CSome["<<this<<"] created moving ["<<&s<<"]" << std::endl; }
CSome& operator=(CSome&& s) { std::cout << "CSome["<<this<<"] assigned moving ["<<&s<<"]" << std::endl; return *this; }
~CSome() { std::cout << "CSome["<<this<<"] destroyed" << std::endl; }
};
#endif // SOME_H_INCLUDED
//datafile.h
#ifndef DATAFILE_H_INCLUDED
#define DATAFILE_H_INCLUDED
#include "some.h"
class CDataFile
{
public:
protected:
static CSome mSome;
};
static class CDataFileInitializer
{
public:
CDataFileInitializer();
~CDataFileInitializer();
} datafileinitializer;
#endif // DATAFILE_H_INCLUDED
//datafile.cpp
#include "datafile.h"
#include <iostream>
static int nifty_counter = 0; //the one and only
CSome CDataFile::mSome; //define and initialize
CDataFileInitializer::CDataFileInitializer()
{
std::cout << "CDataFileInitializer["<<this<<"] creation"<< std::endl;
if(!nifty_counter++)
{
std::cout << "CDataFileInitializer FIRST INITIALIZATION"<< std::endl;
}
}
CDataFileInitializer::~CDataFileInitializer()
{
std::cout << "CDataFileInitializer["<<this<<"] destruction"<< std::endl;
if(!--nifty_counter)
{
std::cout << "CDataFileInitializer LAST DESTRUCTION"<< std::endl;
}
}
//A.cpp
#include <iostream>
static class A
{
public:
A() { std::cout << "initializing A.cpp" << std::endl; }
~A() { std::cout << "cleaning A.cpp" << std::endl; }
} a;
#include "datafile.h"
// other a.cpp code ...
void call_a() { std::cout << "do something in a.ccp" << std::endl; }
//B.cpp
#include <iostream>
static class B
{
public:
B() { std::cout << "initializing B.cpp" << std::endl; }
~B() { std::cout << "cleaning B.cpp" << std::endl; }
} b;
#include "datafile.h"
// other b.cpp code ...
void call_b() { std::cout << "do something in b.ccp" << std::endl; }
//main.cpp
#include <iostream>
void call_a();
void call_b();
int main()
{
std::cout << "main" << std::endl;
call_a();
call_b();
std::cout << "main return" << std::endl;
return 0;
}
даст следующий вывод:
CDataFileInitializer[0x406035] creation
CDataFileInitializer FIRST INITIALIZATION
CSome[0x40602c] default created
initializing A.cpp
CDataFileInitializer[0x406029] creation
initializing B.cpp
CDataFileInitializer[0x406025] creation
main
do something in a.ccp
do something in b.ccp
main return
CDataFileInitializer[0x406025] destruction
cleaning B.cpp
CDataFileInitializer[0x406029] destruction
cleaning A.cpp
CSome[0x40602c] destroyed
CDataFileInitializer[0x406035] destruction
CDataFileInitializer LAST DESTRUCTION
Конечно, адреса будут меняться в зависимости от вашей машины и работы.