如何从命名空间中重载运算符<<
How to overload the operator<< from within a namespace
这是我能想到的最小的包含示例。
首先是 class 的 header。每当使用 << 运算符时,这个 class 应该简单地打印它包含的一个双精度值。
#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
我做错了什么?
亲切的问候,
乔里斯
您希望 using namespace EU;
将所有后续代码放在 namespace EU
中,但它不会(否则您的 int main
也会在命名空间中!)。这只是将该名称空间中已有的东西带入范围。
这意味着您在命名空间内声明友元函数,但在全局范围内定义 new 函数。调用前者将失败,因为它没有定义。
删除 using namespace
,然后将 namespace EU { }
包围在 euro.cpp
中的所有内容。
从此更改您的 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 文件中的代码定义为位于命名空间内。您之前所做的是声明您的命名空间在该文件的全局范围内使用,因为您没有将源代码定义在命名空间内。
这是我能想到的最小的包含示例。 首先是 class 的 header。每当使用 << 运算符时,这个 class 应该简单地打印它包含的一个双精度值。
#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
我做错了什么?
亲切的问候, 乔里斯
您希望 using namespace EU;
将所有后续代码放在 namespace EU
中,但它不会(否则您的 int main
也会在命名空间中!)。这只是将该名称空间中已有的东西带入范围。
这意味着您在命名空间内声明友元函数,但在全局范围内定义 new 函数。调用前者将失败,因为它没有定义。
删除 using namespace
,然后将 namespace EU { }
包围在 euro.cpp
中的所有内容。
从此更改您的 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 文件中的代码定义为位于命名空间内。您之前所做的是声明您的命名空间在该文件的全局范围内使用,因为您没有将源代码定义在命名空间内。