---- main.cpp
#include "head.h"
int main()
{
func1();
}
---- head.h
//#pragma once
#ifndef _HEADDDD
#define _HEADDDD
#include <iostream>
using namespace std;
int g_number;
void func1();
#endif
---- func.cpp
#include "head.h"
void func1()
{
cout<<"func1 "<<g_number<<endl;
}
头文件head.h被包含了两次,结果导致g_number变量产生了重定义。
那么我想问问,#ifndef _HEADDDD这样的条件编译,或者#pragma once,到底是用来解决什么的?
如何才能在头文件中定义变量?(比如许多const变量肯定是想要在项目中的不同地方使用的)请不要告诉我写在cpp里然后用extern声明。
11 个解决方案
#1
h中extern int g_number;cpp中int g_number;
#2
其它法暂未发现,请理解变量的声明式和定义式
#3
//#pragma once
#ifndef _HEADDDD //建议改为: #ifndef HEAD_H
#define _HEADDDD
#include <iostream>
using namespace std;
extern int g_number; //头文件中一般只声明,在.cpp文件中定义
void func1();
#endif
#4
既然你都希望const变量在头文件中定义方便到处引用,你为何不把它改为const类型的,你试过吗?
还是自己动手吧,常量的定义当然可以放在头文件里面。
还是自己动手吧,常量的定义当然可以放在头文件里面。
#5
补充问题:
1 既然有条件编译指令了,那么为什么中间的内容还是在不同模块被编译了2次最终导致符号重复?
2 假设我想在头文件里定义一个全局变量,在不同的cpp文件之间交叉访问,用extern的话显然不能方便的使用。因为我不知道应该在哪个cpp文件才去定义那个没有extern的实体。
1 既然有条件编译指令了,那么为什么中间的内容还是在不同模块被编译了2次最终导致符号重复?
2 假设我想在头文件里定义一个全局变量,在不同的cpp文件之间交叉访问,用extern的话显然不能方便的使用。因为我不知道应该在哪个cpp文件才去定义那个没有extern的实体。
#6
一般编程都是采用的这种方法。
#7
透过本质看现象:
1.
int g_number; // 定义式,不管你放在哪里,它也是定义式。定义式需要分配内存,所以一个变量的定义式应该只有一个,而且只能有一个。你的头文件被多处包含,相当于定义了多个定义式,所以报错是必然的。
extern int g_number; // 声明式,不分配内存,可以有N多个。放在头文件中,被包含多次,无所谓。
2.
如果你有一个头文件叫"head.h",放你的声明式。
一般会有一个cpp文件叫"head.cpp",放你的定义式。
这样,不存在你想的不方便。
#8
今天突然想通了。。
我收到java影响过深,下意识的认为一个文件中的变量要想在另一个文件中使用就必须import这个文件,而C加加中根本不是这样。想要使用本文件中未声明的变量,我根本不必关心它是在哪个文件定义的,甚至不必知道他是否真的被定义过,只要不负责任的声明为外部变量就行,到时候链接器会替我找那变量的本体所在。。。
关于条件编译我想向高手请教一下,是否可以这样理解:“条件编译只在同一个编译单元中有效”
假如我有src1.cpp何src2.cpp同时包含了head.h,虽然head.h中有条件编译语句,但是src1.cpp和src2.cpp属于不同的编译单元,所以它会在src1.cpp和src2.cpp中分别编译一次。虽然编译的时候没有冲突,但是到了链接的时候,冲突就显现出来了。
我收到java影响过深,下意识的认为一个文件中的变量要想在另一个文件中使用就必须import这个文件,而C加加中根本不是这样。想要使用本文件中未声明的变量,我根本不必关心它是在哪个文件定义的,甚至不必知道他是否真的被定义过,只要不负责任的声明为外部变量就行,到时候链接器会替我找那变量的本体所在。。。
关于条件编译我想向高手请教一下,是否可以这样理解:“条件编译只在同一个编译单元中有效”
假如我有src1.cpp何src2.cpp同时包含了head.h,虽然head.h中有条件编译语句,但是src1.cpp和src2.cpp属于不同的编译单元,所以它会在src1.cpp和src2.cpp中分别编译一次。虽然编译的时候没有冲突,但是到了链接的时候,冲突就显现出来了。
#9
差不多就是LZ那意思。
#10
别差不多啊 具体差多少?
学程序眼里揉不得沙子啊。。
学程序眼里揉不得沙子啊。。
#11
我自己的体验说一下,编译有很多步骤,头文件的编译会被生成在头文件名作用域下的一序列信息,如类型,变量,函数等。而条件编译就是避免被重复的编译,解决类型重定义和提高编译速度。当如果头文件有lz说的有定义
变量和函数,这些变量和函数就会被生成全局变量,当被多次包含时,就会多次生成全局变量,当链接时,编译器
不能确定你的全局变量是哪一个,故出现链接错误。
变量和函数,这些变量和函数就会被生成全局变量,当被多次包含时,就会多次生成全局变量,当链接时,编译器
不能确定你的全局变量是哪一个,故出现链接错误。
#1
h中extern int g_number;cpp中int g_number;
#2
其它法暂未发现,请理解变量的声明式和定义式
#3
//#pragma once
#ifndef _HEADDDD //建议改为: #ifndef HEAD_H
#define _HEADDDD
#include <iostream>
using namespace std;
extern int g_number; //头文件中一般只声明,在.cpp文件中定义
void func1();
#endif
#4
既然你都希望const变量在头文件中定义方便到处引用,你为何不把它改为const类型的,你试过吗?
还是自己动手吧,常量的定义当然可以放在头文件里面。
还是自己动手吧,常量的定义当然可以放在头文件里面。
#5
补充问题:
1 既然有条件编译指令了,那么为什么中间的内容还是在不同模块被编译了2次最终导致符号重复?
2 假设我想在头文件里定义一个全局变量,在不同的cpp文件之间交叉访问,用extern的话显然不能方便的使用。因为我不知道应该在哪个cpp文件才去定义那个没有extern的实体。
1 既然有条件编译指令了,那么为什么中间的内容还是在不同模块被编译了2次最终导致符号重复?
2 假设我想在头文件里定义一个全局变量,在不同的cpp文件之间交叉访问,用extern的话显然不能方便的使用。因为我不知道应该在哪个cpp文件才去定义那个没有extern的实体。
#6
一般编程都是采用的这种方法。
#7
透过本质看现象:
1.
int g_number; // 定义式,不管你放在哪里,它也是定义式。定义式需要分配内存,所以一个变量的定义式应该只有一个,而且只能有一个。你的头文件被多处包含,相当于定义了多个定义式,所以报错是必然的。
extern int g_number; // 声明式,不分配内存,可以有N多个。放在头文件中,被包含多次,无所谓。
2.
如果你有一个头文件叫"head.h",放你的声明式。
一般会有一个cpp文件叫"head.cpp",放你的定义式。
这样,不存在你想的不方便。
#8
今天突然想通了。。
我收到java影响过深,下意识的认为一个文件中的变量要想在另一个文件中使用就必须import这个文件,而C加加中根本不是这样。想要使用本文件中未声明的变量,我根本不必关心它是在哪个文件定义的,甚至不必知道他是否真的被定义过,只要不负责任的声明为外部变量就行,到时候链接器会替我找那变量的本体所在。。。
关于条件编译我想向高手请教一下,是否可以这样理解:“条件编译只在同一个编译单元中有效”
假如我有src1.cpp何src2.cpp同时包含了head.h,虽然head.h中有条件编译语句,但是src1.cpp和src2.cpp属于不同的编译单元,所以它会在src1.cpp和src2.cpp中分别编译一次。虽然编译的时候没有冲突,但是到了链接的时候,冲突就显现出来了。
我收到java影响过深,下意识的认为一个文件中的变量要想在另一个文件中使用就必须import这个文件,而C加加中根本不是这样。想要使用本文件中未声明的变量,我根本不必关心它是在哪个文件定义的,甚至不必知道他是否真的被定义过,只要不负责任的声明为外部变量就行,到时候链接器会替我找那变量的本体所在。。。
关于条件编译我想向高手请教一下,是否可以这样理解:“条件编译只在同一个编译单元中有效”
假如我有src1.cpp何src2.cpp同时包含了head.h,虽然head.h中有条件编译语句,但是src1.cpp和src2.cpp属于不同的编译单元,所以它会在src1.cpp和src2.cpp中分别编译一次。虽然编译的时候没有冲突,但是到了链接的时候,冲突就显现出来了。
#9
差不多就是LZ那意思。
#10
别差不多啊 具体差多少?
学程序眼里揉不得沙子啊。。
学程序眼里揉不得沙子啊。。
#11
我自己的体验说一下,编译有很多步骤,头文件的编译会被生成在头文件名作用域下的一序列信息,如类型,变量,函数等。而条件编译就是避免被重复的编译,解决类型重定义和提高编译速度。当如果头文件有lz说的有定义
变量和函数,这些变量和函数就会被生成全局变量,当被多次包含时,就会多次生成全局变量,当链接时,编译器
不能确定你的全局变量是哪一个,故出现链接错误。
变量和函数,这些变量和函数就会被生成全局变量,当被多次包含时,就会多次生成全局变量,当链接时,编译器
不能确定你的全局变量是哪一个,故出现链接错误。