0

节目#1

// file.h
class File
{
public:
    static const int var = 9;
};

-

// main.cpp
#include <iostream>
#include "file.h"
using namespace std;

int main() {
    File f;
    cout << f.var;
    return 0;
}

节目#2

// file.h
int GlobalVar ;
class File
{
public:
    static const int var = 9;
};

-

// main.cpp
extern int GlobalVar;

#include <iostream>
#include "file.h"
using namespace std;

int main() {
    cout << GlobalVar;
    return 0 ;
}

程序#1 运行良好,但程序#2 给出链接器错误:

error LNK2005: "int GlobalVar" (?x@@3HA) already defined in file.obj

我知道头文件永远不会被编译。那么在上述情况下,编译器如何知道变量 var 的定义,却找不到GlobalVar? 这两个程序有什么区别?

4

2 回答 2

7

当你使用

#include "some_header.h"

或者

#include <some_header.h>

这些include指令直接*被预处理器替换为some_header.h.

因此,当您编译cpp文件时,它实际上包含some_header.h. 这就是这段代码的编译方式。

* - 如果你有包含守卫,我会跳过内容,如果它已经包含在其他标题中


编辑:关于您的编辑 - 关于extern:这不是正确的方法。

extern int GlobalVar ;

应该放在标题中,并且

int Globalvar ;

应该在cpp文件中。你应该阅读更多关于extern它是如何工作的以及它是做什么的(提示:假设你只想有一个变量,在一个地方定义并且可以在多个 cpp 文件中访问 - 你会怎么做?有很多SO中的问题也是关于这个案例的)。

于 2012-12-21T13:54:07.513 回答
0

对静态 const 数据成员有一定的限制,类似于对内联函数的允许(在类声明中或标记为内联的头文件中定义的函数)。对于原始类型(例如整数)的静态 const 数据成员,允许在头文件中定义它们,即使这在技术上会导致违反单一定义规则 (ODR),因为对于此类原始类型并假设所有链接器看到的那些数据成员的实例来自同一个头文件,可以安全地假设它们都是相等的。而且因为它们是常量,所以拥有许多副本(或完全优化它们)没有问题,但如果是非常量,则必须保证单个实例被操纵。并且因为它们是原始类型(具有微不足道的构造函数),所以不存在静态数据成员(在多个翻译单元中)的多重构造的副作用问题,但如果是非原始类型,则必须保证构造在静态初始化期间只发生一次。因此,很明显,这个例外规则不适用于非常量和/或非原始(类类型)的静态数据成员,在这种情况下,它们必须仅在一个翻译单元中定义(一个编译的 cpp 文件) .

于 2012-12-23T05:12:15.893 回答