老鸟问一个菜鸟问题。。。。

behire123 2015-09-07 05:12:45
好久没有写代码,今天被一个问题难道了,虽然知道怎么解决,但是还是有点不太明白。
比如我有4个文件:
文件一:a.h
#ifndef __AAA_H
#define __AAA_H
int max(int a, int b)
{
return a > b ? a : b;
}

#endif

文件2:b.cpp
#include "a.h"

int getMax(int a, int b)
{
return max(a, b);
}

文件3:c.cpp
#include "a.h"

int getvalue(int a, int b)
{
return max(a, b);
}

文件4:main.cpp
#include <stdio.h>
#include <stdlib.h>

extern int getvalue(int a, int b);

int main(int argc, char *argv[])
{
printf("getval:%d.\n", getvalue(10, 20));
return 1;
}

g++ -o x b.cpp c.cpp main.cpp

c.cpp:(.text+0x0): multiple definition of `max(int, int)'

为啥会报重复定义?a.h中的 #ifndef 这个东西没起作用了?
...全文
109 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
behire123 2015-09-07
  • 打赏
  • 举报
回复
引用 5 楼 JiangWenjie2014 的回复:
[quote=引用 2 楼 behire123 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] 请遵循.h文件中写函数原型,.cpp文件中实现函数的通行做法。
头文件中的 #ifndef 都不能保证 这个头文件只引用一次吗?[/quote] 头文件引用一次只局限于某个cpp文件来说的。比如a.h这个文件,当编译器编译b.cpp时保证a.h只被include一次;当编译器编译c.cpp时保证a.h只被include一次,这是ifndef...define...endif的作用。因为每个cpp都要生成一个临时的o文件,当编译b.cpp时,max函数被编译到b.o中,当编译c.cpp时,max函数被编译到c.o中,当编译main.cpp时,找不到max的定义需要链接,最终在链接阶段,max同时出现在b.o和c.o中,报错,重定义。所以你的问题就是不要在头文件中出现函数,对象,数值之类的定义,容易产生重定义的问题。[/quote] 厉害。
xiaoyao18301 2015-09-07
  • 打赏
  • 举报
回复
a.h b.cpp c.cpp main.cpp 如果单独编译b c是没问题的,可是你选择的一起编译,这就造成了头文件重复引用
赵4老师 2015-09-07
  • 打赏
  • 举报
回复
引用 4 楼 iyomumx 的回复:
非要在头文件里写函数体,请用static inline 不论是#ifndef还是#pragma once都只保证头文件在一个编译单元中只出现一次,然而你的程序至少有3个编译单元
佩服!
JiangWenjie2014 2015-09-07
  • 打赏
  • 举报
回复
引用 2 楼 behire123 的回复:
[quote=引用 1 楼 zhao4zhong1 的回复:] 请遵循.h文件中写函数原型,.cpp文件中实现函数的通行做法。
头文件中的 #ifndef 都不能保证 这个头文件只引用一次吗?[/quote] 头文件引用一次只局限于某个cpp文件来说的。比如a.h这个文件,当编译器编译b.cpp时保证a.h只被include一次;当编译器编译c.cpp时保证a.h只被include一次,这是ifndef...define...endif的作用。因为每个cpp都要生成一个临时的o文件,当编译b.cpp时,max函数被编译到b.o中,当编译c.cpp时,max函数被编译到c.o中,当编译main.cpp时,找不到max的定义需要链接,最终在链接阶段,max同时出现在b.o和c.o中,报错,重定义。所以你的问题就是不要在头文件中出现函数,对象,数值之类的定义,容易产生重定义的问题。
iyomumx 2015-09-07
  • 打赏
  • 举报
回复
非要在头文件里写函数体,请用static inline 不论是#ifndef还是#pragma once都只保证头文件在一个编译单元中只出现一次,然而你的程序至少有3个编译单元
赵4老师 2015-09-07
  • 打赏
  • 举报
回复
VC编译选项加/EP /P(项目、属性、配置属性、C/C++、预处理器、预处理到文件:是,预处理取消显示行号:是),重新编译,查看宏展开后对应的.i文件。gcc加-E http://bbs.csdn.net/topics/391003898
behire123 2015-09-07
  • 打赏
  • 举报
回复
引用 1 楼 zhao4zhong1 的回复:
请遵循.h文件中写函数原型,.cpp文件中实现函数的通行做法。
头文件中的 #ifndef 都不能保证 这个头文件只引用一次吗?
赵4老师 2015-09-07
  • 打赏
  • 举报
回复
请遵循.h文件中写函数原型,.cpp文件中实现函数的通行做法。

64,676

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧