我偶然发现了一个我可以解决的问题,但我不确定它为什么不起作用。
这是我尝试使用的代码。为了简洁起见,已经剥离了字段。让我知道他们是否需要,我会把它们放回去:
#pragma once
#ifndef __PageStyle__
#define __PageStyle__
class PageStyle
{
public:
friend bool operator<(const PageStyle& lhs, const PageStyle& rhs);
};
bool operator<(const PageStyle& lhs, const PageStyle& rhs)
{
return (lhs.name < rhs.name);
}
#endif
在我的源文件中,我做了类似的事情:
#include "PageStyle.h"
...
void PageStyleManager::loadPageStyles() {
std::set<PageStyle> pageStyles;
...
}
代码编译得很好,但链接器吐了出来:
1>PageStyleManager.obj : error LNK2005: "bool __cdecl operator<(class PageStyle const &,class PageStyle const &)" (??M@YA_NABVPageStyle@@0@Z) already defined in BaseContentFiller.obj
BaseContentFiller是PageStyleManager的基类,也是以类似方式使用PageStyle的其他类。
经过深入研究后,我发现为了我的目的(使用STL集中的类)我毕竟不需要非成员朋友版本。 我让运营商成为内联公共成员,代码链接没有问题。
为什么会出现这个问题?我确保我使用了标头防护装置,这是我第一次使用操作员重载的真实体验,我想知道我做错了什么。
答案 0 :(得分:10)
如果您在头文件中包含该功能的定义,则会在包含头文件的每个 Translation unit 中定义该功能。
这违反了 One Definition Rule ,因此违反了链接器错误。
请注意,标头保护或#pragma once
只是阻止相同的头文件多次包含在同一源文件中,但不会在不同的TU中定义它。
有两种解决方案可以解决问题:
cpp
文件或inline
。答案 1 :(得分:6)
不要在头文件中定义operator<
;只需在那里声明它,并在.cpp
文件中定义它。 #pragma once
只是使头文件在同一.cpp
文件中多次包含,但它可能包含在不同的.cpp
文件中,在这种情况下,链接器将看到多个定义operator<
。