如何在命名空间中重载operator<<运算符

3

这是我想到的最小的示例。 首先是类的头文件。只要使用 << 运算符,该类应该简单地打印它所包含的一个双精度数。

#pragma once
#ifndef EURO_H
#define EURO_H

#include <ostream>

namespace EU
{
   class Euro final
   {
   public:
        explicit Euro(double value);
        virtual ~Euro() = default;

        double getValue() const;

        friend std::ostream& operator<<(std::ostream &os, const Euro &euro);

    private:
        double m_value;
    };
}

#endif // EURO_H

现在是 .cpp 文件。
#include "euro.h"

using namespace EU;

Euro::Euro(double value)
{
    m_value = value;
}

double Euro::getValue() const
{
    return m_value;
}

std::ostream& operator<<(std::ostream &os, const Euro &euro)
{
    os << euro.getValue() << "EUR";
    return os;
}

最后,是主要代码 main.cpp

#include "euro.h"

#include <iostream>

using namespace EU;

int main()
{
    auto e = Euro(3.14);
    std::cout << e << std::endl;
}

然而,当我使用以下方式进行编译时:

g++ -std=c++11 *.cpp

出现以下错误:

/tmp/ccP7OKC5.o: In function `main':
main.cpp:(.text+0x35): undefined reference to `EU::operator<<(std::ostream&, EU::Euro const&)'
collect2: error: ld returned 1 exit status

我做错了什么?

祝好, 乔里斯


你可以进一步简化它,完全不需要 value,只需尝试打印一个静态值! - Lightness Races in Orbit
作为提示,您不需要同时使用 #pragma once 和头文件保护 #ifndef ... #define .... #endif - Francis Cugler
2个回答

10

您希望using namespace EU;将所有后续代码置于namespace EU内,但它不会这样做(否则您的int main也将在该命名空间中!)。这只是将已经存在于该命名空间中的内容引入到作用域内。

这意味着您在命名空间中声明了友元函数,但在全局范围内定义了一个新的函数。对前者的调用将失败,因为没有对其进行定义。

删除using namespace,并将namespace EU { }包装在euro.cpp的所有内容中。


0
将您的cpp文件从这个改为:
#include "euro.h"

using namespace EU;

Euro::Euro(double value)
{
    m_value = value;
}

double Euro::getValue() const
{
    return m_value;
}

std::ostream& operator<<(std::ostream &os, const Euro &euro)
{
    os << euro.getValue() << "EUR";
    return os;
}

转换为:

#include "euro.h"

namespace EU {  

Euro::Euro(double value)
{
    m_value = value;
}

double Euro::getValue() const
{
    return m_value;
}

std::ostream& operator<<(std::ostream &os, const Euro &euro)
{
    os << euro.getValue() << "EUR";
    return os;
}

} // namespace EU

这个定义了cpp文件中的代码属于哪个命名空间。之前你所做的是在文件的全局范围内声明你的命名空间,因为你没有将源代码定义在命名空间内。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接