首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在何处声明struct运算符重载

在何处声明struct运算符重载
EN

Stack Overflow用户
提问于 2020-02-03 15:55:18
回答 2查看 431关注 0票数 1

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

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

代码语言:javascript
复制
#pragma once

namespace utils { 

    struct astTime
    {
        int hour;
        int min;
        double secs;
    };

    double round(double number, int decPlace);
}

我还有一个源文件,在这里我实现了round函数。

为了在Boost测试中使用该结构,我在boost测试文件(.cpp)中定义了这两个操作符:

代码语言:javascript
复制
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测试源文件中删除,方法如下:

代码语言:javascript
复制
#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中已经定义的第二个定义被忽略

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-02-03 16:07:59

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

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

票数 1
EN

Stack Overflow用户

发布于 2020-02-03 16:16:12

通常,在编写类时,您将声明与类相同的标题和命名空间中的所有运算符。这使得类的所有用户都可以在类的对象上使用相同的操作符集。这个规则可能有例外(例如,将IO操作符放在单独的头中以减少编译时间),但一般的经验法则仍然有效。

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

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60042762

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档