首页 > 解决方案 > 在哪里声明结构运算符重载

问题描述

我是 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;
    }
}

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

我已将其移至头文件(因为我不知道在哪里声明它),将它们从 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 std::basic_ostream > &,struct utils::astTime const &)" (??6utils@@YAAAV?$basic_ostream@DU?$ char_traits@D@std@@@std@@AAV12@ABUastTime@0@@Z) 已经在 Utils.obj 中定义;第二个定义被忽略

标签: c++booststructoperator-overloading

解决方案


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

您是否还在标题中定义运算符是一个单独的问题。通常,当它们是轻量级的并且需要在调用站点内联时,您会在标题中提供定义。此外,如果运算符是模板,您通常会在标题中提供定义。

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


推荐阅读