Ошибка компиляции оператора в C ++

0

Я пытаюсь создать программу для имитации игры "Броненосец" в 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]â

Очевидно, что не очень опытные классы. Вообще.

Теги:
class
operator-overloading

3 ответа

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.

  • 0
    Я сделал функцию «друг» в сочетании с последним комментарием @AndyG. Я хорошо компилирую (ууууу!), Но когда я запускаю его, я получаю ошибку сегментации. Я читал, что это обычно вызвано попыткой доступа к фрагменту памяти, к которому у меня нет доступа, или, по крайней мере, мне не разрешено делать с ним то, что я пытаюсь сделать. Хотелось бы, чтобы это дало мне понять, откуда возникла ошибка. Есть идеи?
  • 0
    @UnworthyToast Смотрите мой обновленный пост.
4

Следующая строка не делает то, что вы намереваетесь:

  Ship operator<<(const Ship&);

Вы не можете вернуть Ship и первый параметр должен быть типа ostream когда вы перегружаете оператор <<. Его тип возврата должен быть std::ostream& Из одного из ответов из этого потока: C++ Перегрузка оператора

Операторы потока, среди наиболее часто перегруженных операторов, являются двоичными инфиксными операторами, для которых синтаксис не указывает ограничений на то, должны ли они быть членами или нечленами. Поскольку они изменяют свой левый аргумент (они изменяют состояние потоков), они должны, в соответствии с эмпирическими правилами, быть реализованы как члены их типа левых операндов. Однако их левые операнды являются потоками из стандартной библиотеки, и хотя большинство операторов вывода потока и ввода, определенных стандартной библиотекой, действительно определяются как члены классов потоков, когда вы реализуете операции вывода и ввода для своих собственных типов, вы не может изменять стандартные типы потоков библиотек. Вот почему вам необходимо реализовать эти операторы для ваших собственных типов как функции, не являющиеся членами.

Один из способов - реализовать его с канонической формой:

std::ostream& operator<<(std::ostream& os, const Ship& obj)
{
    // write obj information
    return os;
 }
  • 0
    И как я могу получить мой перегруженный оператор, чтобы иметь возможность использовать ship_loc? Я думал, что поскольку я объявил ship_loc в классе, прежде чем определить его в конструкторе, он сможет использоваться любым классом, но, очевидно, нет.
  • 0
    @UnworthyToast: ship_loc является членом Ship , поэтому вы можете использовать функцию obj.ship_loc[0] сказать obj.ship_loc[0] и т. Д.
Показать ещё 3 комментария
0

Вы перегружаете operator<< неправильно, подпись, которую вы хотите, это что-то вроде:

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню