.h文件和.cpp文件在编译时有区别!哈哈。

时间:2021-11-21 11:55:16
我举一个异常简单的例子:
这是main.CPP:
#include "test.h"
//include "test.cpp"
int main(int argc, char *argv[])
{
return 0;
}

这是test.h:
//test.h就一句话
int i=999;

编译,没有问题。

如果我仅仅把.h后缀改为.cpp,然后用同样的方法,编译直接提示i重定义。
怎么回事?仅仅是文件后缀名改变了,其余都是一样的。

16 个解决方案

#1


h文件不包含是不会单独编译的,cpp文件会对应一个obj文件

#2


代码和文件后缀没关系的吧

至于i重定义,清理一遍再编译看看,就一个i也不可能有重定义啊

#3


.h里面的定义都是内部链接的,是局部的。
.cpp里面的除非明确声明为局部的,则为全局的。

#4


改成cpp 之后test.cpp单独编译一次  然后包含test.cpp又 编译一次 
就发现了重定义

#5


引用 1 楼 jackyjkchen 的回复:
h文件不包含是不会单独编译的,cpp文件会对应一个obj文件

现在.H文件是包含进去了的。

#6


引用 5 楼 superqing 的回复:
引用 1 楼 jackyjkchen 的回复:
h文件不包含是不会单独编译的,cpp文件会对应一个obj文件

现在.H文件是包含进去了的。

包含进去也不会单独编译,而是和cpp文件一起存在于一个obj中,总之h文件不单独编译

#7


引用 3 楼 adventurelw 的回复:
.h里面的定义都是内部链接的,是局部的。
.cpp里面的除非明确声明为局部的,则为全局的。

不对吧,现在我把main改为:
main.CPP: 
#include "test.h" 
int main(int argc, char *argv[])
{
printf("%d\n",i);
return 0;
}
按照你的说法,i是局部的,我在main.cpp里面根本没有extern过,那怎么可以照常使用呢?哈哈,你解释一下?
非const对象都是默认extern的,const对象才是默认内部作用域的。

#8


LZ。。。。

#9


引用 8 楼 traceless 的回复:
LZ。。。。


铅哥,这好问题呢,从来没想过。。。。

#10


引用 6 楼 jackyjkchen 的回复:
引用 5 楼 superqing 的回复:
引用 1 楼 jackyjkchen 的回复:
h文件不包含是不会单独编译的,cpp文件会对应一个obj文件

现在.H文件是包含进去了的。

包含进去也不会单独编译,而是和cpp文件一起存在于一个obj中,总之h文件不单独编译

现在我把main改为: 
main.CPP: 
#include "test.h" 
int main(int argc, char *argv[]) 

printf("%d\n",i); 
return 0; 

足以证明i是分配了空间的,要不然怎么可能使用呢?
.h不单独编译????你在.H里面乱打几个字符,看看编译是否通过????
另外,手工Makefile 一下就知道,仅仅用test.h,也是生成了test.obj的!

#11


改一下:

这是test.h: 
//test.h就一句话 
int i=999; 

这是添加的test.cpp: 
//test.cpp就一句话 
#include "test.h" 

这是main.CPP: 
#include "test.h" 
int main(int argc, char *argv[]) 

   return 0; 
}



然后你再看看.h文件里面的定义会不会被提示重定义。

#12


引用 9 楼 dontkissbossass 的回复:
引用 8 楼 traceless 的回复:
LZ。。。。


铅哥,这好问题呢,从来没想过。。。。

我从第一次学C++到现在,也有10年了,写了n多程序,也从来没有想过,因为我从来不在.H里面定义extern对象,只声明,今天偶然在.H里面定义了一个全部外部变量,然后到处包含这个文件,居然能通过,觉得奇怪。

#13


引用 2 楼 yxwsbobo 的回复:
代码和文件后缀没关系的吧

至于i重定义,清理一遍再编译看看,就一个i也不可能有重定义啊

你把我那几句话放在VC里面编译一下?

#14


引用 10 楼 superqing 的回复:
引用 6 楼 jackyjkchen 的回复:
引用 5 楼 superqing 的回复:
引用 1 楼 jackyjkchen 的回复:
h文件不包含是不会单独编译的,cpp文件会对应一个obj文件

现在.H文件是包含进去了的。

包含进去也不会单独编译,而是和cpp文件一起存在于一个obj中,总之h文件不单独编译

现在我把main改为:
main.CPP:
#include "test.h"
int main(int argc, char *argv[])
{
printf("%d\n",i);
return 0;
}
足以证明i是分配了空间的,要不然怎么可能使用呢?
.h不单独编译????你在.H里面乱打几个字符,看看编译是否通过????
另外,手工Makefile 一下就知道,仅仅用test.h,也是生成了test.obj的!

别用Makefile指定h,因为Makefile根本不管你的扩展名,标准的Makefile里面只有cpp和c文件(标准的gcc命令行和cl命令行不也不会明确指定h文件么?),不会有h文件,这就是我说h文件不编译的原因!

#15


首先:.h 是不会生成.obj文件的,那是因为LZ你之前改成.cpp生成的。

其次:你改成了.cpp,又#include "test.cpp",要知道编译器对每个.cpp文件都会生成一个.obj文件,
然后再把各个obj组合起来形成exe。这下你知道为什么会重复定义了吧。

然后:你在.h文件里定义int i = 0;那是因为include 时,把这个“包”进了obj,此时编译器当然为
它申请了空间了。

#16


引用 15 楼 traceless 的回复:
首先:.h 是不会生成.obj文件的,那是因为LZ你之前改成.cpp生成的。

其次:你改成了.cpp,又#include "test.cpp",要知道编译器对每个.cpp文件都会生成一个.obj文件,
然后再把各个obj组合起来形成exe。这下你知道为什么会重复定义了吧。

然后:你在.h文件里定义int i = 0;那是因为include 时,把这个“包”进了obj,此时编译器当然为
它申请了空间了。

你说对了,我犯了一个低级错误,没有清理上次的obj,

#1


h文件不包含是不会单独编译的,cpp文件会对应一个obj文件

#2


代码和文件后缀没关系的吧

至于i重定义,清理一遍再编译看看,就一个i也不可能有重定义啊

#3


.h里面的定义都是内部链接的,是局部的。
.cpp里面的除非明确声明为局部的,则为全局的。

#4


改成cpp 之后test.cpp单独编译一次  然后包含test.cpp又 编译一次 
就发现了重定义

#5


引用 1 楼 jackyjkchen 的回复:
h文件不包含是不会单独编译的,cpp文件会对应一个obj文件

现在.H文件是包含进去了的。

#6


引用 5 楼 superqing 的回复:
引用 1 楼 jackyjkchen 的回复:
h文件不包含是不会单独编译的,cpp文件会对应一个obj文件

现在.H文件是包含进去了的。

包含进去也不会单独编译,而是和cpp文件一起存在于一个obj中,总之h文件不单独编译

#7


引用 3 楼 adventurelw 的回复:
.h里面的定义都是内部链接的,是局部的。
.cpp里面的除非明确声明为局部的,则为全局的。

不对吧,现在我把main改为:
main.CPP: 
#include "test.h" 
int main(int argc, char *argv[])
{
printf("%d\n",i);
return 0;
}
按照你的说法,i是局部的,我在main.cpp里面根本没有extern过,那怎么可以照常使用呢?哈哈,你解释一下?
非const对象都是默认extern的,const对象才是默认内部作用域的。

#8


LZ。。。。

#9


引用 8 楼 traceless 的回复:
LZ。。。。


铅哥,这好问题呢,从来没想过。。。。

#10


引用 6 楼 jackyjkchen 的回复:
引用 5 楼 superqing 的回复:
引用 1 楼 jackyjkchen 的回复:
h文件不包含是不会单独编译的,cpp文件会对应一个obj文件

现在.H文件是包含进去了的。

包含进去也不会单独编译,而是和cpp文件一起存在于一个obj中,总之h文件不单独编译

现在我把main改为: 
main.CPP: 
#include "test.h" 
int main(int argc, char *argv[]) 

printf("%d\n",i); 
return 0; 

足以证明i是分配了空间的,要不然怎么可能使用呢?
.h不单独编译????你在.H里面乱打几个字符,看看编译是否通过????
另外,手工Makefile 一下就知道,仅仅用test.h,也是生成了test.obj的!

#11


改一下:

这是test.h: 
//test.h就一句话 
int i=999; 

这是添加的test.cpp: 
//test.cpp就一句话 
#include "test.h" 

这是main.CPP: 
#include "test.h" 
int main(int argc, char *argv[]) 

   return 0; 
}



然后你再看看.h文件里面的定义会不会被提示重定义。

#12


引用 9 楼 dontkissbossass 的回复:
引用 8 楼 traceless 的回复:
LZ。。。。


铅哥,这好问题呢,从来没想过。。。。

我从第一次学C++到现在,也有10年了,写了n多程序,也从来没有想过,因为我从来不在.H里面定义extern对象,只声明,今天偶然在.H里面定义了一个全部外部变量,然后到处包含这个文件,居然能通过,觉得奇怪。

#13


引用 2 楼 yxwsbobo 的回复:
代码和文件后缀没关系的吧

至于i重定义,清理一遍再编译看看,就一个i也不可能有重定义啊

你把我那几句话放在VC里面编译一下?

#14


引用 10 楼 superqing 的回复:
引用 6 楼 jackyjkchen 的回复:
引用 5 楼 superqing 的回复:
引用 1 楼 jackyjkchen 的回复:
h文件不包含是不会单独编译的,cpp文件会对应一个obj文件

现在.H文件是包含进去了的。

包含进去也不会单独编译,而是和cpp文件一起存在于一个obj中,总之h文件不单独编译

现在我把main改为:
main.CPP:
#include "test.h"
int main(int argc, char *argv[])
{
printf("%d\n",i);
return 0;
}
足以证明i是分配了空间的,要不然怎么可能使用呢?
.h不单独编译????你在.H里面乱打几个字符,看看编译是否通过????
另外,手工Makefile 一下就知道,仅仅用test.h,也是生成了test.obj的!

别用Makefile指定h,因为Makefile根本不管你的扩展名,标准的Makefile里面只有cpp和c文件(标准的gcc命令行和cl命令行不也不会明确指定h文件么?),不会有h文件,这就是我说h文件不编译的原因!

#15


首先:.h 是不会生成.obj文件的,那是因为LZ你之前改成.cpp生成的。

其次:你改成了.cpp,又#include "test.cpp",要知道编译器对每个.cpp文件都会生成一个.obj文件,
然后再把各个obj组合起来形成exe。这下你知道为什么会重复定义了吧。

然后:你在.h文件里定义int i = 0;那是因为include 时,把这个“包”进了obj,此时编译器当然为
它申请了空间了。

#16


引用 15 楼 traceless 的回复:
首先:.h 是不会生成.obj文件的,那是因为LZ你之前改成.cpp生成的。

其次:你改成了.cpp,又#include "test.cpp",要知道编译器对每个.cpp文件都会生成一个.obj文件,
然后再把各个obj组合起来形成exe。这下你知道为什么会重复定义了吧。

然后:你在.h文件里定义int i = 0;那是因为include 时,把这个“包”进了obj,此时编译器当然为
它申请了空间了。

你说对了,我犯了一个低级错误,没有清理上次的obj,