Reputation: 825
I am trying to make a program to simulate playing Battleship in 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;
}
Whenever I try to compile this it give me:
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]â
Obviously not very experienced with classes yet. At all.
Upvotes: 0
Views: 1583
Reputation: 310980
You declared operator <<
as a member function
Ship operator<<(const Ship&);
It means that the left operand is an instance of class Ship. So it could be called as
Ship a, b;
a << b;
But it is obvious that you did not want this.
if you want to output an object of class Ship in output stream then the operator has to be a non-member function. You could define it as a friend function of the class. for example
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
};
And then you could define it as for example the following way
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;
}
Also as the number of coordinates is fixed then there is no need to use std::vector
. Use instead std::array<std::pair<int, int>, 4>
Also remove statement
std::vector<std::pair<int, int>> ship_loc; //Ship location
from the constructor. It is a local variable. You need to fill data member ship_loc instead of this local variable.
Upvotes: 4
Reputation: 23634
The following line does not do what you intend to be:
Ship operator<<(const Ship&);
You cannot return Ship
and the first parameter has to be of ostream
type when you overload the <<
operator. Its return type has to be std::ostream&
.Quoting from one of the answers from this thread: C++ Operator Overloading
The stream operators, among the most commonly overloaded operators, are binary infix operators for which the syntax specifies no restriction on whether they should be members or non-members. Since they change their left argument (they alter the stream’s state), they should, according to the rules of thumb, be implemented as members of their left operand’s type. However, their left operands are streams from the standard library, and while most of the stream output and input operators defined by the standard library are indeed defined as members of the stream classes, when you implement output and input operations for your own types, you cannot change the standard library’s stream types. That’s why you need to implement these operators for your own types as non-member functions.
One way is to implement it with the canonical form:
std::ostream& operator<<(std::ostream& os, const Ship& obj)
{
// write obj information
return os;
}
Upvotes: 4
Reputation: 27577
You're overloading operator<<
incorrectly, the signature you want is something like:
std::ostream& operator<<(std::ostream& os, const Ship& s);
Upvotes: 0