繁体   English   中英

Friend运算符重载会导致“已定义的”链接器错误

[英]Friend operator overloading causes “already defined in” linker errors

我偶然发现了一个我可以解决的问题,但我不确定它为什么不起作用。

这是我试图使用的代码。 为了简洁起见,已经剥离了字段。 让我知道他们是否需要,我会把它们放回去:

#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集中使用类)我毕竟不需要非成员朋友版本。 我让操作员成为一个内联的公共成员,并且代码链接没有问题

为什么会出现这个问题? 我确保我使用过标题保护,这是我第一次遇到运算符重载的真实体验,我想知道我做错了什么。

如果在头文件中包含函数的定义,则会在包含头文件的每个转换单元中定义它。
这违反了One Definition Rule ,因此违反了链接器错误。

请注意,标题保护或#pragma once只是阻止相同的头文件多次包含在同一源文件中,但不能在不同的TU中定义它。

有两种解决方案可以解决问题:

  1. 只需在头文件中添加声明,并在一个cpp文件中添加定义
  2. 使标题中定义的函数为inline

不要在头文件中定义operator< ; 只需在那里声明它,并在.cpp文件中定义它。 #pragma once只是让头文件在同一个.cpp文件中多次被包含,但它可能包含在不同的.cpp文件中,在这种情况下,链接器将看到operator<多个定义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM