I have recently encountered a behavior in C++ program that I cannot entirely understand. Let me explain the behavior via simple example.
1. First static library
At the very bottom of hierarchy, I have a static library - lets name it FirstLIB. This library includes two pairs of header/source files. The sample.h header file contains MyClass class definition. Corresponding sample.cpp file contains implementation of this class (its methods). The code is presented below:
sample.h
#ifndef __sample_h
#define __sample_h
namespace SampleNamespace
{
class MyClass
{
int counter;
public:
MyClass();
int GetCounter();
void SetCounter(int value);
};
}
#endif
and sample.cpp
#include <iostream>
#include "sample.h"
namespace SampleNamespace
{
MyClass::MyClass(): counter(0)
{
std::cout << "Inside of MyClass constructor!" << std::endl;
}
int MyClass::GetCounter() { return counter; }
void MyClass::SetCounter(int value) { counter = value; }
}
Onwards, the dvcl.h file declares simple API used to manipulate MyClass object and dvcl.cpp implements this API. It's important to notice that dvcl.cpp file contains definition of MyClass object that is used by the methods of this API. The variable is defines as static so it will be visible only inside of this source file.
dvcl.h
#ifndef _dvcl_h
#define _dvcl_h
void DVCL_Initialize(int counter);
int DVCL_GetCounter();
void DVCL_SetCounter(int value);
#endif
dvcl.cpp
#include "dvcl.h"
#include "sample.h"
static SampleNamespace::MyClass myClass;
void DVCL_Initialize(int counter)
{
myClass.SetCounter(counter);
}
int DVCL_GetCounter()
{
return myClass.GetCounter();
}
void DVCL_SetCounter(int value)
{
myClass.SetCounter(value);
}
2. Second static library
Second static library - lets name it SecondLIB - is even simpler than the first one. It only contains one header/source pair. The dvconference_client.h header declares one function, while dvconference_client.cpp implements this function. dvconference_client.cpp also includes dvcl.h header file (which will trigger compilation of dvcl.cpp source). The code can be found below:
dvconference_client.h
#ifndef __external_file
#define __external_file
int DoSomething();
#endif
dvconference.cpp
#include "dvconference_client.h"
#include "dvcl.h"
int DoSomething()
{
return DVCL_GetCounter();
}
3. Main executable
And finally, the main executable MainEXE includes only one main.cpp file. This source includes dvconference_client.h and dvcl.h headers. The code is presented below:
#include <iostream>
#include "dvconference_client.h"
#include "dvcl.h"
int main()
{
std::cout << DoSomething() << std::endl;
std::cout << DVCL_GetCounter() << std::endl;
return 0;
}
4. My doubts and questions:
- If I don't call a function that references myClass object (so DoSomething() or one of DVCL_ functions), the MyClass constructor is not invoked. I expected that myClass object will be instantiated by default as dvcl.cpp is compiled. However, it appears that compiler generates needed statements only if it understand that object is actually used in runtime. Is this really true?
- If particular header file (in this case dvcl.h) is included in different sources, the corresponding dvcl.cpp is compiled only once. I remember reading something about this, however I'm not sure that this is really true. Is it actually correct that C++ compiler will compile every source file only once, regardless of how many the corresponding header file is included.
- myClass object defined in dvcl.cpp is instantiated only once. If I correctly understand the 2nd point and if dvcl.cpp is compiled only once, then there is nothing to question here.
I hope more experienced colleagues can clear my doubts (and I apologize for very long post).
For referenec, stages of compilation source-code --> pre-processing --> compilation --> linking --> loading --> execution
Yes, ".c/.cpp" file are compiled only once. But header are parsed per inclusion.
Yes object is executed only once because corresponding object-file is linked and loaded only once.