定义常量数据成员
Defining a constant datamember
节目#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文件)中定义。
- 如果类在 C++ 中具有常量或引用类型的非静态数据成员,为什么编译器不提供默认赋值运算符?
- C++中的常量对象或私有/常量数据成员(变量)?
- 如何强制实施有关指针数据成员的常量正确性
- 现在允许重新定义 constexpr 静态数据成员吗?(但不是内联常量)?
- 错误 C2864:'element::next':只能在类 (STRUCT) 中初始化静态常量整数数据成员
- 我应该使用类内发起器初始化静态常量数据成员还是在其类外的定义中初始化静态常量数据成员
- 警告:ISO C++禁止将静态“constexpr char*”数据成员的字符串常量转换为“char*”
- 将非静态数据成员与常量成员进行比较
- 了解常量引用对非成本数据成员的分配
- 移动具有常量数据成员或引用成员的类的ctor
- 多个数据成员的常量初始化
- 将基元类型的数据成员作为常量引用返回
- C++中常量数据成员的用法
- 类中只能初始化静态常量积分数据成员
- 常量成员函数可以修改数据成员
- 静态断言用于检查静态常量类数据成员
- 非静态常量数据成员的意义何在
- 组合常量和非常量引用数据成员的单个类
- 在编码时在类中声明非静态常量数据成员是否合适?
- 将类的静态常量数据成员初始化为类