定义常量数据成员

Defining a constant datamember

本文关键字:数据成员 常量 定义      更新时间:2023-10-16

节目#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的定义的呢?这两个项目有什么不同?

使用

#include "some_header.h"

#include <some_header.h>

这些include指令直接由含有some_header.h内容的预处理器*代替。

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

* -如果你有include守卫,内容可以跳过,如果它已经包含在其他标题


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

extern int GlobalVar ;

应该放在头文件

中。
int Globalvar ;

应该在cpp文件中。您应该阅读更多关于extern的内容,以了解它是如何工作的以及它做什么(提示:假设您希望只有一个变量,在一个地方定义并在多个cpp文件中可访问-您将如何做到这一点?

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