赞
踩
我们都知道变量或者函数在一个项目中可以存在多次声明,但定义只能出现一次,如果出现多次,编译或链接时就会报multiple definition问题。下面就该问题简要探讨一下:
- // f.h
- int a = 1;
-
- // g.h
- #include "f.h"
-
- // main.cpp
- #include "f.h"
- #include "g.h"
- int main()
- {
- }
- > g++ -o main main.cpp
- In file included from g.h:1:0,
- from main.cpp:2:
- f.h:1:5: error: redefinition of ‘int a’
- int a = 1;
- ^
- In file included from main.cpp:1:0:
- f.h:1:5: note: ‘int a’ previously defined here
- int a = 1;
main.cpp重复包含头文件f.h,等于定义两次变量a。
头文件中加上宏保护#ifndef ...或者#pragma once,保证头文件在一个cpp文件编译过程中只会被包含一次。
- // 修改后的f.h
- #ifndef F_H_
- #define F_H_
-
- int a = 1;
-
- #endif
头文件加上宏保护就一定能防止重定义了吗?显然不能,如
- // f.h
- #ifndef F_H_
- #define F_H_
-
- int a; // 不加extern关键字,就是定义
-
- #endif
-
- // f.cpp
- #include "f.h"
-
- // main.cpp
- #include "f.h"
-
- int main()
- {
- }

- > g++ -o main main.cpp f.cpp
- /usr/bin/ld: /tmp/ccjDbdBf.o:(.data+0x0): multiple definition of `a'; /tmp/cc50XAei.o:(.data+0x0): first defined here
- collect2: error: ld returned 1 exit status
宏保护只能保证头文件在一个cpp文件编程过程中不被重复包含,因此编译生成main.o,f.o是没有问题的,但是链接时发现main.o,f.o中都存在变量a的定义。
不要在头文件中定义变量或函数。
- // 修改后的f.h
- #ifndef F_H_
- #define F_H_
-
- extern int a;
-
- #endif
-
- // 修改后的f.cpp
- #include "f.h"
-
- int a = 1;
注意这里说的是变量,如果头文件定义的是常量如const int a = 1;,被不同cpp包含时,编译和链接时不会报错。原因见C++ primer中的一段话
const int bufSize = 1024; // 缓冲区大小,编译器将在编译过程中把变量bufSize都替换成1024。
为了执行上述替换, 编译器必须知道变量的初始值。如果程序包含多个文件, 则每个用了const对象的文件都必须能访问到它的初始值才行。要做到这一点, 就必须在每一个用到变量的文件中都有对它的定义。为了支持这一用法, 同时避免对同一变量的重复定义, 默认情况下, const对象被设定为仅在文件内有效。当多个文件中出现了同名的const变量时, 其实等同于在不同文件中分别定义了独立的变量。
做到以上两点基本能解决平时80%的重定义问题,那还有20%呢?
1. 两个cpp文件中定义了相同的全局变量
解决:a)换个名字,简单直接。b)如果不愿改名,那就至少要在其中一个变量定义前加上static或者const修饰。
解释:static修饰的变量或者函数只在当前编译单元内可见,不会与那些全局可见性的同名变量冲突。
还有其它场景欢迎补充。。。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。