函数重定义错误

baidu_27192001 2015-04-07 12:46:19
#ifndef ORT_H
#define ORT_H
#include<cmath>
#include<iostream>

class Ort
{
public:
Ort(int einX=0, int einY=0);
int getX() const;
int getY() const;
void aendern(int x, int y);
private:
int xKoordinate;
int yKoordinate;
};

void Ort::aendern(int x, int y)
{
xKoordinate=x;
yKoordinate=y;
}
#endif

这是头文件。aendern的实现就放在头文件中。那么问题来了:
编译结果是aendern重定义。但是如果给aendern加上inline关键字的话,错误就消失了。另外把实现分离出头文件也能运行正常
请问为什么会这样,具体是什么原理。
...全文
260 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
paschen 版主 2015-04-08
  • 打赏
  • 举报
回复
如果多个文件中多次包含同一个头文件,里面的代码会被展开多次,这就导致了重定义 至于加上inline就成为内联函数了,而内联函数的代码会在任何调用它的地方展开,所以调用N次也就是N次重复的代码补充到调用的位置,所以不会出现重定义
ri_aje 2015-04-08
  • 打赏
  • 举报
回复
引用 14 楼 baidu_27192001 的回复:
谢谢 我上面的想法确实错了,从template的角度来看压制重定义的能力感觉确实是没跑了的。 另外c++ 14 3.2/h 这去哪看啊
2014 年版 c++ 国际标准,第三章第二节第六段。
ri_aje 2015-04-07
  • 打赏
  • 举报
回复
引用 6 楼 baidu_27192001 的回复:
谢谢, ifdef基本理解了 就是编译和链接的问题 但是关于inline关键字允许重复定义 可以具体说说吗 重复定义这种事情不管在哪都感觉是不怎么合理的 如果inline允许重复定义 是否意味着我可以给同一个函数编写不同的函数体,那么他在编译时又将调用哪个。
有些实体必须允许重定义,但要保证每一个定义都是完全相同的,这样多个定义和一个定义就没有可观测的区别了。比如定义在头文件的 class,在包含进不同 cpp 的时候,一定在每一个 cpp 中都有一个定义,因为 include 就是强行文字展开吗。 至于你担心的通过 inline 给出可能不同的多个定义的问题,你能先给写个能编译的例子贴上来吗?
勤奋的小游侠 2015-04-07
  • 打赏
  • 举报
回复
多个cpp包含多个函数定义,生成obj是单独生成的,但连接时把它们连在一起编译器就发现,草,怎么这么多定义,于是报错
xiaohuh421 2015-04-07
  • 打赏
  • 举报
回复
函数或者变量放到.h中都很容易出现重复定义的问题. 不管你弄个progma once 还是搞定define , 你都会发现不好使. 正规的解决办法, 还是老老实实把 这些东西移动到.cpp文件中去吧.
helloworldyu 2015-04-07
  • 打赏
  • 举报
回复
首先 inline 是干嘛的要搞清楚。为了去掉函数调用的开销。在编译的时候。每个调用这个函数的地方都会出现一份,比 inline函数的指令集。所以需要在每个调用此函数的地方,都能看到 inline 函数所有指令集。
baidu_27192001 2015-04-07
  • 打赏
  • 举报
回复
谢谢 我上面的想法确实错了,从template的角度来看压制重定义的能力感觉确实是没跑了的。 另外c++ 14 3.2/h 这去哪看啊
bear234 2015-04-07
  • 打赏
  • 举报
回复
我这样跟你说: 你在思考这个问题的时候,可以把inline视为“默认static” 但是你一定要记住,inline不是static.............. 总之你可以暂时这样理解,但是inline确实不是static,一定要记住~~~
baidu_27192001 2015-04-07
  • 打赏
  • 举报
回复
谢谢, ifdef基本理解了 就是编译和链接的问题
但是关于inline关键字允许重复定义 可以具体说说吗
重复定义这种事情不管在哪都感觉是不怎么合理的
如果inline允许重复定义 是否意味着我可以给同一个函数编写不同的函数体,那么他在编译时又将调用哪个。
ri_aje 2015-04-07
  • 打赏
  • 举报
回复
引用 11 楼 baidu_27192001 的回复:
可不可以这样理解 在编译的时候每个inline函数都被摊开了。 在链接时,函数调用已被函数体替换,因为函数本身都不在存在,也就更说不上重定义了。 至于“通过inline给出可能不同的多个定义”, 我刚开始是这么想的,在Ort类声明下,直接写了两个aendern实现。结果果然是不行的。所以我觉得“inline允许重定义”这中说法是意指不明确的。他看似允许重定义,其实是因为inline的约定,导致函数被摊开了,从而避免了重定义。
不行。inline 展开只是建议,是否展开由编译器自行决定,因此不能假设所有 inline 函数都在调用点展开了,对于展开不了的,你的说法就解释不通了。对于过于复杂的函数或函数模板,展开没有好处,编译器一般还是当普通函数处理,生成调用指令。inline 是 c++ 语言层面上的概念,理解的时候不要和具体实现细节捆绑。 inline 压制重定义的能力是 c++ 中另一个叫 one definition rule (odr) 的重要概念的副作用,odr 还赋予了一些其它实体类似的待遇,比如 class,non-static function template,同时也对他们享受待遇的具体条件做了规范,具体见 c++14 3.2/5.
ri_aje 2015-04-07
  • 打赏
  • 举报
回复
inline 关键字允许重复定义,所以没有问题。 ifdef 只能解决同一个头文件不会在同一个 cpp (或头文件) 中多次包含的问题,解决不了成员函数重定义的问题,后者是因为同一个头文件在不同 cpp 中多次包含导致的。
baidu_27192001 2015-04-07
  • 打赏
  • 举报
回复
可不可以这样理解 在编译的时候每个inline函数都被摊开了。 在链接时,函数调用已被函数体替换,因为函数本身都不在存在,也就更说不上重定义了。 至于“通过inline给出可能不同的多个定义”, 我刚开始是这么想的,在Ort类声明下,直接写了两个aendern实现。结果果然是不行的。所以我觉得“inline允许重定义”这中说法是意指不明确的。他看似允许重定义,其实是因为inline的约定,导致函数被摊开了,从而避免了重定义。
baidu_27192001 2015-04-07
  • 打赏
  • 举报
回复
被鼠标玩死了。。。。 头文件里包含有 #ifndef ORT_T #define ORT_T . . . #endif 所以应该不会出现重复加载的问题 另外在aendern实现前加上关键字inline 则运行顺利 这才是让人头疼的地方
baidu_27192001 2015-04-07
  • 打赏
  • 举报
回复
打错了 void Ort::aendern(int x, int y)
{
xKoordinate=x;
yKoordinate=y;
} void Ort::aendern(int x, int y)
{
xKoordinate=x;
yKoordinate=y;
}是
#ifndef ORT_T\
#define ORT_T
.
.
.
#endif

aendern实现前定义为inline 则运行顺利
baidu_27192001 2015-04-07
  • 打赏
  • 举报
回复
头文件前已经加了#ifndef ORT_T 应该不会出现上述问题吧 另外 关键是为什么加上iniine后问题就顺利通过了
ri_aje 2015-04-07
  • 打赏
  • 举报
回复
#include 展开后会把对应都文件的内容插入到 include 点,多个 cpp #include 这个头文件就会导致 aendern 的定义出现在多个 cpp 文件中,从而导致重定义。

64,647

社区成员

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

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