我最近在C++程序中遇到了一個我無法完全理解的行爲。讓我通過簡單的例子來解釋行爲。與編譯,靜態初始化和靜態庫有關的問題
一是靜態庫
在層次結構的最底層,我有一個靜態庫 - 讓它命名爲FirstLIB。這個庫包含兩對頭文件/源文件。 sample.h頭文件包含MyClass類定義。對應sample.cpp文件包含此類的實現(其方法)。該代碼介紹如下:
sample.h
#ifndef __sample_h
#define __sample_h
namespace SampleNamespace
{
class MyClass
{
int counter;
public:
MyClass();
int GetCounter();
void SetCounter(int value);
};
}
#endif
和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; }
}
起,dvcl.h文件聲明用於處理簡單的API MyClass對象和dvcl.cpp實現此API。需要注意的是,dvcl.cpp文件包含此API的方法使用的MyClass對象的定義。該變量被定義爲靜態的,所以它只能在這個源文件中可見。
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.第二靜態庫
二靜態庫 - 讓它命名爲SecondLIB - 是甚至比第一個更簡單。它只包含一個頭/源對。 dvconference_client.h標頭聲明一個函數,而dvconference_client.cpp實現此功能。 dvconference_client.cpp還包含dvcl.h頭文件(這將觸發dvcl.cpp源文件的編譯)。該代碼可以發現如下:
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.主要可執行
最後,主可執行文件MainEXE只包含一個main.cpp文件。該源代碼包含dvconference_client.h和dvcl.h頭文件。該代碼介紹如下:
#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.我的疑惑和問題:
- 如果我不叫引用myClass的對象(所以DoSomething的()或DVCL_功能之一的功能),MyClass構造函數不被調用。我期望myClass對象將在編譯dvcl.cpp時默認實例化。但是,看起來編譯器只在知道對象實際在運行時使用時纔會生成所需的語句。這是真的嗎?
- 如果特定的頭文件(本例中爲dvcl.h)包含在不同的源中,則相應的dvcl.cpp僅被編譯一次。我記得有關這方面的東西,但我不確定這是否屬實。無論對應的頭文件包含多少,C++編譯器是否只編譯一次每個源文件實際上是正確的。
- 在dvcl.cpp中定義的myClass對象僅實例化一次。如果我正確理解第二點,並且如果dvcl.cpp只編譯一次,那麼這裏沒有什麼可質疑的。
我希望更有經驗的同事可以清除我的疑惑(我很抱歉發了很長的帖子)。