我最近在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只编译一次,那么这里没有什么可质疑的。
我希望更有经验的同事可以清除我的疑惑(我很抱歉发了很长的帖子)。