c++中操作符重载编译错误

Operator overloading compile error in C++

本文关键字:编译 错误 重载 操作符 c++      更新时间:2023-10-16

我正在尝试制作一个程序来模拟在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]â

显然对类还不是很有经验。div。

您将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,而不是这个局部变量。

下面这行并没有达到你想要的效果:

  Ship operator<<(const Ship&);

当您重载<<操作符时,您不能返回Ship并且第一个参数必须为ostream类型。它的返回类型必须是std::ostream&。引用来自这个线程的一个答案:c++ Operator重载

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

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

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

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

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