对于const常量定义在头文件的思考
2017-08-01 20:47
447 查看
今天在看effective C++ title02 时,看到一句话:由于常量定义式通常被放在头文件中(以便被不同的源码含入)。感觉十分困惑,因为在我的印象中,变量是不能定义在头文件中的,会引起重复定义的错误。
c++primer原文: 默认状态下,const对象仅在文件中有效
当以编译时初始化的方式定义一个const对象时,就如对bufSize的定义一样:
const int bufSize = 512:
为了执行上述替换,编译器必须知道变量的初始值。如果程序包含多个文件,则每个用了const对象的文件都必须得能访问到它的初始值才行。要做到这一点,就必须在每一个用到变量的文件中都有对它的定义。为了支持这一用法,同时避免对同一变量的重复定义,默认情况下,const对象被设定为仅在文件内有效。当多个文件中出现同名的const变量时,其实等同于在不同文件中分别定义了独立的变量。(注意是等同于 分别 定义了 一份)
某些时候有这样一种const变量,它的初始值不是一个常量表达式,但又确实有必要在文件间共享。这种情况下,我们不希望编译器为每个文件分别生成独立的变量。相反,我们想让这类const对象像其他(非常量)对象一样工作,也就是说,只在一个文件中定义const,而在其他文件中声明并使用它。
解决的办法是,对于const变量不管是声明还是定义都添加extern关键字,这样只需定义一次就可以了
file.cpp:
extern const int bufSize = fcn();
file.h:
extern const int bufSize;
Note:如果想在多个文件之间共享const对象,必须在变量的定义之前添加extern关键字
相似的,static变量也是仅在文件中有效
但是extern跟static是不允许同时出现的
******************************************************************************************************************************************************
其实不光是变量的定义不能出现在头文件中(当然除了上面讲的作用域为本文件的外),函数的定义也是不能出现在头文件中的
如:
vectortest.h
listtest.h
listtest.cpp
main.cpp
这是VS报的错
1>main.obj : error LNK2005: "public: void __thiscall Base::testVector(void)" (?testVector@Base@@QAEXXZ) 已经在 listtest.obj 中定义
1>D:\VS2013_Solution\STL_test\Debug\STL_test.exe : fatal error LNK1169: 找到一个或多个多重定义的符号
(这里的例子举的并不好,因为其实是类的成员函数重复定义了,其实我写的第一个例子是关于函数的,只要把Base类去掉,单独留下函数就行。我写类是看看类的函数定义能不能在头文件,当然肯定是不能的了)
这样编译会报一个链接错误,因为在 listtest.h 中包含了 vectortest.h的头文件,而且函数的定义是写在头文件中的,函数默认就是extern的,那么就会引起重复定义,链接报错
其实只要记住,不管是变量还是函数,都将声明放在头文件,定义放在cpp文件,那么就肯定不会搞错了
和其他函数不一样,内联函数和constexpr函数可以在程序中多次定义。毕竟,编译器要想展开函数仅有函数声明是不够的,还需要函数的定义。不过,对于某个给定的内联函数或者constexpr函数来说,它的多个定义必须完全一致。基于这个原因,内联函数和constexpr函数通常定义在头文件中。
c++primer原文: 默认状态下,const对象仅在文件中有效
当以编译时初始化的方式定义一个const对象时,就如对bufSize的定义一样:
const int bufSize = 512:
为了执行上述替换,编译器必须知道变量的初始值。如果程序包含多个文件,则每个用了const对象的文件都必须得能访问到它的初始值才行。要做到这一点,就必须在每一个用到变量的文件中都有对它的定义。为了支持这一用法,同时避免对同一变量的重复定义,默认情况下,const对象被设定为仅在文件内有效。当多个文件中出现同名的const变量时,其实等同于在不同文件中分别定义了独立的变量。(注意是等同于 分别 定义了 一份)
某些时候有这样一种const变量,它的初始值不是一个常量表达式,但又确实有必要在文件间共享。这种情况下,我们不希望编译器为每个文件分别生成独立的变量。相反,我们想让这类const对象像其他(非常量)对象一样工作,也就是说,只在一个文件中定义const,而在其他文件中声明并使用它。
解决的办法是,对于const变量不管是声明还是定义都添加extern关键字,这样只需定义一次就可以了
file.cpp:
extern const int bufSize = fcn();
file.h:
extern const int bufSize;
Note:如果想在多个文件之间共享const对象,必须在变量的定义之前添加extern关键字
相似的,static变量也是仅在文件中有效
但是extern跟static是不允许同时出现的
******************************************************************************************************************************************************
其实不光是变量的定义不能出现在头文件中(当然除了上面讲的作用域为本文件的外),函数的定义也是不能出现在头文件中的
如:
vectortest.h
#ifndef __VECTORTEST_H__ #define __VECTORTEST_H__ #include <iostream> #include <vector> #include <stdint.h> class Base { public: typedef std::vector<int32_t> VecInt; typedef std::vector<int32_t>::iterator VecIntIt; void testVector(); /*{ VecInt a; a.push_back(1); a.push_back(2); for (VecIntIt it = a.begin(); it != a.end(); ++it) { std::cout << *it << std::endl; } }*/ }; void Base::testVector() { VecInt a; a.push_back(1); a.push_back(2); for (VecIntIt it = a.begin(); it != a.end(); ++it) { std::cout << *it << std::endl; } } #endif
listtest.h
#ifndef __LIST_H__ #define __LIST_H__ #include "vectortest.h" void testList(); #endif
listtest.cpp
#include "listtest.h" void testList() { Base a; a.testVector(); }
main.cpp
#include <iostream> using namespace std; #include <stdint.h> #include "vectortest.h" #include "listtest.h" int32_t main() { Base a; a.testVector(); testList(); system("pause"); return 0; }
这是VS报的错
1>main.obj : error LNK2005: "public: void __thiscall Base::testVector(void)" (?testVector@Base@@QAEXXZ) 已经在 listtest.obj 中定义
1>D:\VS2013_Solution\STL_test\Debug\STL_test.exe : fatal error LNK1169: 找到一个或多个多重定义的符号
(这里的例子举的并不好,因为其实是类的成员函数重复定义了,其实我写的第一个例子是关于函数的,只要把Base类去掉,单独留下函数就行。我写类是看看类的函数定义能不能在头文件,当然肯定是不能的了)
这样编译会报一个链接错误,因为在 listtest.h 中包含了 vectortest.h的头文件,而且函数的定义是写在头文件中的,函数默认就是extern的,那么就会引起重复定义,链接报错
其实只要记住,不管是变量还是函数,都将声明放在头文件,定义放在cpp文件,那么就肯定不会搞错了
和其他函数不一样,内联函数和constexpr函数可以在程序中多次定义。毕竟,编译器要想展开函数仅有函数声明是不够的,还需要函数的定义。不过,对于某个给定的内联函数或者constexpr函数来说,它的多个定义必须完全一致。基于这个原因,内联函数和constexpr函数通常定义在头文件中。
相关文章推荐
- C语言之变量、常量(define\const)、变量的声明和定义
- php const 用法详解 定义 常量
- 在php中定义常量时,const与define的区别
- php const和define的区别(php类中如何定义常量)
- 用const定义的常量比用#define定义的常量有那些优势
- 在php中定义常量时,const与define的区别
- 实体定义:每一层都不相同,对于层间实体之间映射的一点思考
- ADS1.2不支持用CONST定义的常量作为数组长度
- 在php中定义常量时,const与define的区别
- 在php中定义常量时,const与define的区别
- php中const定义常量
- php中const与define定义常量的区别
- php 中常量定义const和define的区别
- const用法(1) 定义常量
- php const和define的区别(php类中如何定义常量)
- C++系列之基本数据类型、常量、变量、const、引用、typedef、枚举、类类型、编写自己的头文件
- PHP 中 define() 和 const 定义常量时的区别
- php const和define的区别(php类中如何定义常量)
- const变量与define定义常量的区别
- pch文件的使用, 头文件使用, 常量(const)的定义,以及一些常用的宏定义