我是C++的新手(我来自C#)。
我在命名空间中有这样的结构:
#pragma once
namespace utils {
struct astTime
{
int hour;
int min;
double secs;
};
double round(double number, int decPlace);
}我还有一个源文件,在这里我实现了round函数。
为了在Boost测试中使用该结构,我在boost测试文件(.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;
}
}我必须在哪里声明这两个操作符(以及如何声明)?
我将其移至头文件(因为不知道在何处声明IT),将它们从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);
}我得到了以下错误:
警告(??6utils@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV12@ABUastTime@0@@Z):"class std::basic_ostream >& __cdecl utils::operator<<(类std::basic_ostream > &,struct::astTime &)“Utils.obj中已经定义的第二个定义被忽略
发布于 2020-02-03 16:07:59
发布于 2020-02-03 16:16:12
通常,在编写类时,您将声明与类相同的标题和命名空间中的所有运算符。这使得类的所有用户都可以在类的对象上使用相同的操作符集。这个规则可能有例外(例如,将IO操作符放在单独的头中以减少编译时间),但一般的经验法则仍然有效。
您是否也在标题中定义运算符是另一个问题。通常,在标题中提供定义时,它们是轻量级的,并且希望在调用站点进行内联。此外,如果运算符是模板,则通常在标头中提供定义。
您的链接器错误是因为您的操作符定义在标题中,它包含在多个翻译单元(.cpp文件)中。实际上,这意味着定义在包含程序的多个翻译单元中重复,这违反了ODR。要解决这个问题,您可以使用inline标记操作符,这将允许编译器只使用最终程序中的多个定义中的一个(如果它不是在每个调用站点中内联的话)。
https://stackoverflow.com/questions/60042762
复制相似问题