自相矛盾的错误消息 - 运算符重载 <<

Contradictory Error Messages - Operator Overloading <<

问题

根据我在 class 中编写函数的方式,当我尝试重载 << 运算符作为 class 的朋友时,我收到了 2 条相互矛盾的错误消息之一。报错信息如下:

// With two arguments
(engine.cpp) error: 'std::ostream& game::GameEngine::operator<<( std::ostream&, const Engine& )' must take exactly one argument.

否则,如果我尝试编译器所说的,我会得到这个:

// With 1 argument
(engine.h) error: 'std::ostream& game::operator<<( std::ostream& )' must take exactly two arguments.
(engine.cpp) error: no 'std::ostream& game::GameEngine::operator<<( std::ostream& )' member function declared in class 'game::GameEngine'

我认为有两个参数的那个是正确的,但我不明白为什么我会收到相互矛盾的错误消息。我正在使用“-Wall、-Wextra、-pedantic-error、-std=c++11”和其他几个警告标志来编译文件。

代码

engine.h 来源:

#include <iostream>
namespace game {
    // Note that all variables and functions except the operator overload are static.
    class GameEngine {
    public:
      /* ... */
      friend std::ostream& operator<<( std::ostream& o, const GameEngine& engine );
    private:
      /* ... */
    }
    typedef game::GameEngine Engine;

并且,engine.cpp:

#include <iostream>
#include "engine.h"
/* ... */
std::ostream& Engine::operator<<( std::ostream& o, const Engine& engine ) {
    /* ... */
}

当运算符作为非静态成员函数重载时,它比作为非成员函数(或静态成员函数)少一个参数。这是因为在成员版本中有一个隐式参数,即调用对象。因此二元运算符重载,如 operator<<,在写成成员时只接受一个参数。这个参数是调用operator时右边取的,左边是调用对象

这就是错误消息似乎相互矛盾的原因。您在显示的代码中所做的是将您的函数声明为非成员函数(朋友不是成员),但您已将其定义为成员函数。

在为您的 class 重载输入和输出流运算符的特定情况下,您不能将它们重载为 class 的非静态成员,因为左侧参数需要是流 class.

当您将 class 中的函数声明为友元时,它是封闭命名空间的成员,而不是 class 本身的成员。所以你需要定义为

std::ostream& game::operator<<( std::ostream& o, const Engine& engine ) { ... }