运算符在C ++中重载编译错误

时间:2014-03-21 23:21:38

标签: c++ class operator-overloading

我正在尝试制作一个模拟用C ++演奏战舰的程序

#include <iostream>
#include <vector>

class Ship {
public:
    Ship();
    Ship operator<<(const Ship&);
private:
    int x = 0;
    int y = 0;
    std::vector<std::pair<int, int>> ship_loc;      //Ship location
};

Ship::Ship() {
    srand(time(NULL));
    std::vector<std::pair<int, int>> ship_loc;      //Ship location
    for (int i = 0; i < 4; ++i) {
            x = rand() % 20;
            y = rand() % 20;
            std::pair<int, int> coordinates = std::make_pair(x, y);
            ship_loc.push_back(coordinates);
            //ship_loc.push_back(std::pair<x, y>)
    };
};

Ship operator<<(const Ship &s) {
    std::cout << ship_loc[0] << ship_loc[1] << ship_loc[2] << ship_loc[3]
            << std::endl;
}

int main()
{
    Ship first_ship;
    std::cout << first_ship;
}

每当我尝试编译它时,它会给我:

battleship.cpp:26:30: error: âShip operator<<(const Ship&)â must take exactly two           arguments
battleship.cpp: In function âint main()â:
battleship.cpp:34:25: error: cannot bind âstd::ostream {aka std::basic_ostream<char>}â     lvalue to âstd::basic_ostream<char>&&â
In file included from /usr/include/c++/4.7/iostream:40:0,
             from battleship.cpp:1:
/usr/include/c++/4.7/ostream:600:5: error:   initializing argument 1 of     âstd::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&,     const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = Ship]â

显然对课程没有太多经验。完全没有。

3 个答案:

答案 0 :(得分:4)

以下行不符合您的要求:

  Ship operator<<(const Ship&);

当您重载Ship运算符时,您无法返回ostream且第一个参数必须为<<类型。它的返回类型必须是std::ostream&。引用此帖子的一个答案:C++ Operator Overloading

  
    

最常见的重载运算符中的流运算符是二进制中缀运算符,其语法对它们应该是成员还是非成员没有限制。由于他们改变了他们的左参数(他们改变了流的状态),根据经验法则,他们应该被实现为左操作数类型的成员。 但是,它们的左操作数是来自标准库的流,虽然标准库定义的大多数流输出和输入操作符确实被定义为流类的成员,但是当您为自己实现输出和输入操作时类型,你不能改变标准库的流类型。这就是为什么你需要为你自己的类型实现这些运算符作为非成员函数。

  

一种方法是使用规范形式实现它:

std::ostream& operator<<(std::ostream& os, const Ship& obj)
{
    // write obj information
    return os;
 }

答案 1 :(得分:4)

您将operator <<声明为成员函数

Ship operator<<(const Ship&);

这意味着左操作数是Ship类的实例。所以它可以被称为

Ship a, b;

a << b;

但显然你不想要这个。

如果要在输出流中输出类Ship的对象,则操作符必须是非成员函数。 您可以将其定义为类的友元函数。例如

class Ship {
public:
    Ship();
    friend std::ostream & operator <<( std::ostream &os, const Ship& );
private:
    int x = 0;
    int y = 0;
    std::vector<std::pair<int, int>> ship_loc;      //Ship location
};

然后您可以将其定义为例如以下方式

std::ostream & operator <<( std::ostream &os, const Ship &s) 
{
    os << "( " << s.ship_loc[0].first << ", " << s.ship_loc[0].second << " )" 
       << ", ( " << s.ship_loc[1].first << ", " << s.ship_loc[1].second << " )"
       << ", ( " << <.ship_loc[2].first << ", " << s.ship_loc[3].second << " ) "
       << ", ( " << <.ship_loc[3].first << ", " << s.ship_loc[3].second << " ) "
       << std::endl;

   return os;
}

此外,由于坐标数是固定的,因此无需使用std::vector。请改用std::array<std::pair<int, int>, 4>

同时删除声明

std::vector<std::pair<int, int>> ship_loc;      //Ship location

来自构造函数。这是一个局部变量。您需要填充数据成员ship_loc而不是此局部变量。

答案 2 :(得分:0)

您错误地重载了operator<<,您想要的签名是这样的:

std::ostream& operator<<(std::ostream& os, const Ship& s);