为什么不将操作符重载标记为内联会导致重复定义错误?

Why does this not marking an operator overload as inline cause a duplicate definition error?

本文关键字:定义 错误 操作符 重载 记为 为什么不      更新时间:2023-10-16

创建以下类后,编译失败,出现许多"重复符号"错误。实际的错误并不是很具有描述性:

"重复符号__Zeq.... .://图书馆/开发/上的用户名都用户/dangillmor Xcode/DerivedData/MyProject-asdfasfasdf…/构建/中间体/MyProject.build Debug-iphonesimulator/MyTarget.build Objects-normal/i386/MyClass.o"

上面相同的消息出现在许多不同的类中,并且在编译结束时出现,所以我不知道问题是什么。

我检查了以下内容:

    使用这个的类,包括Listening.hpp文件。这个类的唯一定义在这个文件中。

是什么问题呢?

#ifndef Listening_hpp
#define Listening_hpp
#include <stdio.h>
#include "EAction.hpp"
class Listening{
private:
    int _emitterId;
    int _listenerId;
    std::string _eventName;
    EAction* _actionToTake; //not owned.
protected:
public:
    Listening(int emitterId,int listenerId,std::string eventName,EAction* actionToTake) : _emitterId(emitterId),_listenerId(listenerId),_eventName(eventName){
        _actionToTake = actionToTake;
    }
    int getEmitterId()const{
        return _emitterId;
    }
    int getListenerId()const{
        return _listenerId;
    }
    std::string getEventName()const{
        return _eventName;
    }
    EAction* getAction()const{
        return _actionToTake;
    }
};
bool operator==(const Listening &first,const Listening &other)
{
    bool result = false;
    if(first.getEmitterId() == other.getEmitterId()){
        if(first.getListenerId() == other.getListenerId()){
            if(first.getEventName() == other.getEventName()){
                if (first.getAction() == other.getAction()) {
                    result = true;
                }
            }
        }
    }
    return result;
}
bool operator!=(const Listening &first,const Listening &other)
{
    bool result = !(first == other);
    return result;
}
#endif /* Listening_hpp */

EAction.hpp

#ifndef EAction_hpp
#define EAction_hpp
#include <stdio.h>
class EAction{
private:
protected:
public:
    virtual std::vector<std::size_t> seedList() = 0;
};
#endif /* EAction_hpp */

编辑:编辑标题-我认为这可能有助于那些因为其他原因而有重复定义错误的人忽略这个答案。

头文件中的自由函数必须标记为inline,或者更改为仅在头文件中声明:

inline bool operator==(const Listening &first,const Listening &other)
{

operator!=也类似。

原来的问题是,任何单位包括这个头文件将有它的目标文件包含一个副本的operator==。然后链接器看到这个,不知道哪一个是正确的。inline可以被认为是一个链接指令,说"所有这些函数都是相同的,只是选择一个"。链接到更详细的答案。

同样的问题不会发生在类成员函数体中,因为在类定义内部编写的这些体是隐式的inline


历史注释:最初,inline主要是一个优化指令。然而,现在的编译器足够聪明,可以自己做出优化决策;因此,inline现在的主要用途是曾经的次要效果:避免在头文件中使用函数时出现多个定义错误。


顺便说一句,你可以写return bla;,而不是把bla赋值给bool变量,等等。