在哪里声明结构运算符重载

Where to declare a struct operator overloading

本文关键字:重载 运算符 结构 声明 在哪里      更新时间:2023-10-16

我是C++的新手(我来自C#(。

我在命名空间中有这个结构:

#pragma once
namespace utils { 
struct astTime
{
int hour;
int min;
double secs;
};
double round(double number, int decPlace);
}

我还有一个源文件,我已经在其中实现了round功能。

为了在提升测试中使用该结构,我在提升测试文件 (.cpp( 中定义了这两个运算符:

namespace utils {
bool operator ==(utils::astTime const &left, utils::astTime const &right)
{
return(
left.secs == right.secs
&& left.min == right.min
&& left.hour == right.hour);
}
std::ostream& operator<<(std::ostream& os, const utils::astTime& dt)
{
os << dt.hour << "h " << dt.min << "m " << dt.secs << "s" << std::endl;
return os;
}
}

我必须在哪里声明这两个运算符(以及如何(?

我已将其移动到头文件(因为我不知道在哪里声明它(,将它们从 boost 测试源文件中删除,这样:

#pragma once
#include <iostream>
namespace utils { 
struct astTime
{
int hour;
int min;
double secs;
};
bool operator ==(utils::astTime const &left, utils::astTime const &right)
{
return(
left.secs == right.secs
&& left.min == right.min
&& left.hour == right.hour);
}
std::ostream& operator<<(std::ostream& os, const utils::astTime& dt)
{
os << dt.hour << "h " << dt.min << "m " << dt.secs << "s" << std::endl;
return os;
}
double round(double number, int decPlace);
}

我收到以下错误:

警告LNK4006:"class std::basic_ostream> & __cdecl utils::operator<<(class 标准::basic_ostream> &,结构 utils::astTime const &(" (??6utils@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV12@ABUastTime@0@@Z( 已经在 Utils.obj 中定义;忽略第二个定义

你在代码中混淆了声明和定义。将定义放入实现文件 (*.cpp(。将声明放入标题中,在round声明旁边。

或者,您可以将定义放入标头中并将它们声明inline(这是自定义运算符等短函数的例程(。函数的inline说明符可防止函数在由多个翻译单元包含时违反一个定义规则。

通常,在编写类时,您将在与类相同的标头和命名空间中声明所有运算符。这允许类的所有用户在类的对象上具有相同的运算符集。此规则可能有例外(例如,将 IO 运算符放在单独的标头中以减少编译时间(,但一般的经验法则成立。

是否也在标题中定义运算符是一个单独的问题。通常,当定义是轻量级的并且希望在调用站点内联时,您可以在标头中提供定义。此外,如果运算符是模板,则通常在标头中提供定义。

链接器错误是因为运算符定义位于标头中,该标头包含在多个翻译单元(.cpp 个文件中(。实际上,这意味着定义在组成程序的多个翻译单元中重复,这违反了ODR。要解决此问题,您可以使用inline标记运算符,这将允许编译器在最终程序中仅使用多个定义中的一个(以防它未在每个调用站点中内联(。