Я пытаюсь создать программу для имитации игры "Броненосец" в 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]â
Очевидно, что не очень опытные классы. Вообще.
Вы объявили 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++ Перегрузка оператора
Операторы потока, среди наиболее часто перегруженных операторов, являются двоичными инфиксными операторами, для которых синтаксис не указывает ограничений на то, должны ли они быть членами или нечленами. Поскольку они изменяют свой левый аргумент (они изменяют состояние потоков), они должны, в соответствии с эмпирическими правилами, быть реализованы как члены их типа левых операндов. Однако их левые операнды являются потоками из стандартной библиотеки, и хотя большинство операторов вывода потока и ввода, определенных стандартной библиотекой, действительно определяются как члены классов потоков, когда вы реализуете операции вывода и ввода для своих собственных типов, вы не может изменять стандартные типы потоков библиотек. Вот почему вам необходимо реализовать эти операторы для ваших собственных типов как функции, не являющиеся членами.
Один из способов - реализовать его с канонической формой:
std::ostream& operator<<(std::ostream& os, const Ship& obj)
{
// write obj information
return os;
}
ship_loc
является членом Ship
, поэтому вы можете использовать функцию obj.ship_loc[0]
сказать obj.ship_loc[0]
и т. Д.
Вы перегружаете operator<<
неправильно, подпись, которую вы хотите, это что-то вроде:
std::ostream& operator<<(std::ostream& os, const Ship& s);