C++ 类的成员函数定义在.h中为什么会产生函数重定义错误?

既然定义在.h中,那么类和函数的定义就在一块。
而如果要使用这个类,就必须包含这个头文件。包含了头文件,就能立刻找到函数的定义,不需要链接。
就算多个.cpp中存在函数的多个定义,也没有关系呀

看你的描述,你应该还没有搞清楚什么叫定义,什么叫声明,什么是编译期,什么是链接期。
我简单说一下,如果你需要更详细的解答,建议搜索一个博客或者找找相关的书籍,这个就不是我这边能够给出的范畴了,毕竟我不是写书。

C++类一般在h文件声明,在cpp文件中定义。 所谓声明就是简简单单的函数名,以及参数列表的声明,并不包含函数实现代码。在cpp文件中通过 MyClass::Init() 这样的模式将实现代码填充。在编译期,编译器扫描你包含的头文件的声明,找到这个函数的声明,如果相关的函数名,以及参数检查通过,你的编译期就可以正常通过。

然后进入链接期,它开始根据相关的函数名等标识,寻找相关的cpp代码中的函数实现。如果有多个定义,这个时候链接器就晕菜了,它不知道应该寻找哪一个函数的实现,来生成obj。于是就会报告link error。上面的编译期报告的是compile error,两个完全是不同的概念。

OK,结束。追问

你对编译与链接的理解和我所知的不尽相同。编译期不只是“找到这个函数的声明”,如果能找到函数的定义,应该直接找到定义。如果不能,就将这个函数记录在未解决符号表中,由链接器从其他编译单元中寻找定义。我的问题是,把函数定义在.h中,包含了头文件,就找到了定义。如果在编译期就找到了定义,为什么还要连接?为什么还会产生重定义错误?
另外,希望你戒骄戒躁,虚心钻研

追答

噢,我终于明白你说的意思了。
你的意思是在头文件中有一个class的声明和定义,同时在cpp文件中仍然加入class的某一个成员函数的定义。然后对cpp文件进行编译报告重定义的错误, 是不?

针对这个问题,这个重定义不是链接错误,它是编译期的错误。你的cpp文件由于包含了h文件,因此编译器需要对h文件进行解析,将它的函数声明进入到符号表,函数实现应该会编译成汇编代码(后期会由汇编器转换成机器指令),然后对cpp文件进行解析,这个时候编译器就会发现class的函数又有一个实现,因此就会报告重定义错误。

还有对你的戒骄戒躁,我并不认可。不过知识就是在分歧中得到螺旋式升华的,有不同亦无可厚非。

追问

我是这个意思:F.h: void F(){} 1.cpp: #include"F.h" void main(){F()}
2.cpp: #include"F.h" void ff(){F()}
这样会报error LNK2005的错误。但为什么连接的时候会检查重定义?1.cpp与2.cpp在编译时都能找到F()的定义,F()不在未解决符号表中,链接器没必要去找F()的符号

追答

很久没有看百度知道了,今天才发现。

首先在F.h中,你已经对F()函数进行了定义,这样你在1.cpp和2.cpp进行包含的时候,两个cpp都会有这个函数的定义。在编译期,编译期会根据F.h和1.cpp来编译生成1.o, 然后根据F.h和2.cpp编译生成2.o(请注意,1.o和2.o都有一个对于F函数的定义代码,注意注意是定义,不是声明),最后在链接器链接的时候,它发现在main函数中需要调用F(),于是开始寻找F的定义代码,很显然在1.o可以找到,在2.o也可以找到,那么链接器就晕菜了。同一个F函数,竟然有两个目标文件有定义,它不知道该选择哪一个了,于是就报重定义的链接错误。

温馨提示:内容为网友见解,仅供参考
无其他回答
相似回答