Dealing with operator overload method as a friend - c++

I tried to create simple class and to overload some of it's operators, however, i failed at the very beginning, here's my code:
#include <iostream>
class Person
{
char *firstName;
char *lastName;
int age;
friend std::ostream &operator<<(std::ostream &, const Person &);
public:
Person() : firstName("Piotr"), lastName("Tchaikovsky"), age(10) {}
Person(char* f, char* l, int a)
{
this->firstName = f;
this->lastName = l;
age = a;
}
std::ostream &operator<<(std::ostream& out, const Person &p)
{
out << p.firstName << " " << p.lastName;
return out;
}
};
int main()
{
Person a;
getchar();
getchar();
}
So, before i created this operator overloading function i used debugger to see if constructor is going to work, and it worked, since default values were given correctly to the variable a i created, after that, all i did was that i created function that overloads the operator << and it is a friend function of my class, since i am taught that it is a good thing to do due to the type of the first parameter of overloading function, however, when i try to run this (NOTE: i have not tried to print out anything yet, i wanted to check if everything works fine first) it gives me errors saying:
"too many parameters for this operator function",
"binary 'operator <<' has too many parameters" and
" 'Person::operator<<' :error in function declaration; skipping function body"
however, i can't find any problems with function declaration, and i cannot possibly see how two parameters can be too many for this function. Any help appreciated!

You declare the friend function as a global non-member function. Then you define a member function.
Move the definition of the operator<< function to outside the class:
class Person
{
...
friend std::ostream &operator<<(std::ostream &, const Person &);
...
};
std::ostream &operator<<(std::ostream& out, const Person &p)
{
out << p.firstName << " " << p.lastName;
return out;
}
Or alternatively define the friend function inline:
class Person
{
...
friend std::ostream &operator<<(std::ostream &, const Person &)
{
out << p.firstName << " " << p.lastName;
return out;
}
...
};

Related

Error while overloading <<. What am I doing wrong here?

I am learning C++ and I am working on overloading <<. I am using the below code to print the time from class. It seems to be working with friend function but when I use without friend, it seems to be causing the error "No match for operator<<". What am I doing wrong here? Below is my code:
#include <iostream>
using namespace std;
class Time
{
private:
int hour;
int minute;
int second;
public:
Time(int hh, int mm, int ss)
{
second = ss%60;
mm +=ss/60;
minute = mm%60;
hh +=mm/60;
hour = hh;
}
ostream& operator<<(ostream &out); //overloading << function declaration
};
ostream& Time::operator <<(ostream &out) // overloading << function definition
{
out << "Time - " << hour << ":" << minute << ":" << second;
return out;
}
int main()
{
using namespace std;
Time tm(10,36,60);
cout << tm;
return 0;
}
The function
ostream& operator<<(ostream &out);
defines << such that the LHS is a Time object and RHS is a std::ostream object.
It can be used as:
Time tm(10,36,60);
tm << cout;
not as
cout << tm;
To use
cout << tm;
you need to define a function whose LHS is of type std::ostream. Hence, it cannot be a member function of Time.
Declare the function as:
friend ostream& operator<<(ostream &out, Time const& ti);
and implement it accordingly.
When you have a member operator overload, the left-hand-side of the operator is the object of that class. So your member:
ostream& operator<<(ostream &out);
actually will match usages:
tm << cout
but not cout << tm.
To fix this you should use a non-member function. My preferred way is:
// not inside a class definition
ostream &operator<<(ostream &os, Time const &tm)
{
// output using public methods of tm
return os;
}
However another common technique is to use a friend function:
// Inside Time's class definition
friend ostream &operator<<(ostream &os, Time const &tm)
{
// output using private members of tm
return os;
}
Note that even though the latter appears inside a class definition, it's actually not a member function. The friend keyword makes it so.

How to get THIS when overloading operator in C++

I'm a student learning c++. today, I was making a operator overload function to use it in 'cout'. following is a class that contains name, coordinates, etc.
class Custom {
public:
string name;
int x;
int y;
Custom(string _name, int x, int y):name(_name){
this->x = x;
this->y = y;
}
int getDis() const {
return static_cast<int>(sqrt(x*x+y*y));
}
friend ostream& operator << (ostream& os, const Custom& other);
};
ostream& operator << (ostream& os, const Custom& other){
cout << this->name << " : " << getDis() << endl;; // error
return os;
}
However, this code isn't working because of 'THIS' keyword that I was expecting it points to the object. I want to show the object's name and distance value. How can I solve it? I think it is similar with Java's toString method so that it will be able to get THIS.
Thanks in advance for your answer and sorry for poor english. If you don't understand my question don't hesitate to make a comment.
this is available only in member functions, but your operator<< is not a class member (declaring it as friend does not make it a member). It is a global function, as it should be. In a global function, just use the arguments you are passing in:
ostream& operator << (ostream& os, const Custom& other)
{
os << other.name << " : " << other.getDis() << endl;
return os;
}
Also note os replaced cout in the code above. Using cout was an error - the output operator should output to the provided stream, not to cout always.

Can this be done without using friends?

Can the following code (I only kept the relevant part) be converted to use a static member function rather than a friend free function? If not, why not? I tried to convert it to use a static member function in multiple different ways and failed (kept getting different compiler errors for different variations), but I gathered from the answer to this question that you could use either one to do the same things. Is this not technically true due to some property of C++ syntax? Where am I going wrong here?
class Tape {
public:
friend std::ostream &operator<<(std::ostream &, Tape &);
private:
char blank;
size_t head;
std::string tape;
}
std::ostream &operator<<(std::ostream &out, Tape &tape) {
out << tape.tape << std::endl;
for (size_t i = 0; i < tape.head; i++)
out << ' ';
out << '^' << std::endl;
return out;
}
According to the C++ Standard
6 An operator function shall either be a non-static member function or
be a non-member function and have at least one parameter whose type is
a class, a reference to a class, an enumeration, or a reference to an
enumeration.
So you may not define operator << as a static mamber function of the class.
Nevertheless inside the definition of the operator you may use static member functions.
For example
#include <iostream>
class A
{
private:
int x = 10;
public:
static std::ostream & out( std::ostream &os, const A &a )
{
return ( os << a.x );
}
};
std::ostream & operator <<( std::ostream &os, const A &a )
{
return ( A::out( os, a ) );
}
int main()
{
A a;
std::cout << a << std::endl;
return 0;
}
Opposite to C++ in C# operator functions are defined as static.:)
Since the std::ostream argument is the left hand side of the operator, it can't be a member of your class (static or otherwise).
So it has to be a free function, because you can't add members to std::ostream.
It doesn't have to be a friend though, it could instead call a public member.
I personally prefer this method, as it doesn't expose anything to the outside.
class Tape {
public:
void print(std::ostream &out) const
{
out << tape << std::endl;
for (size_t i = 0; i < head; i++)
out << ' ';
out << '^' << std::endl;
}
};
std::ostream& operator<<(std::ostream &out, const Tape &tape)
{
tape.print(out);
return out;
}

Error Overloading << in C++

So I'm trying to overload the << operator. I have defined in my header file as follows:
&operator<<(std::ostream &o, const gVector3 &v)
And I've defined it in my cpp file like this:
std::ostream &gVector3::operator<<(std::ostream &o, const gVector3 &v){
return o << "The vector elements are" << v[0] << v[1] << v[2];
}
I get the following error message. Does anyone know why?
C:\Qt\Tools\QtCreator\bin\Homework1\gVector3.cpp:112: error: 'std::ostream& gVector3::operator<<(std::ostream&,
const gVector3&)' must take exactly one argument
std::ostream &gVector3::operator<<(std::ostream &o, const gVector3 &v){
Your help is very much appreciated!
^
You've put the declaration inside a class definition, which for the compiler means that it's a member function - operators as class members can only take one argument. The other argument is the object you'll be calling it on. Example for easier understanding:
struct Foo {
void operator<<(int) { }
};
int main()
{
Foo f;
f << 5;
// can be also called like this:
f.operator<<(5);
}
What you need is a friend specifier to tell the compiler that you're declaring a non-member:
friend std::ostream& operator<<(std::ostream &o, const gVector3 &v)
Another example this time with non-member:
struct Foo {
friend void operator<<(Foo, int) { }
};
int main()
{
Foo f;
f << 5;
// this time, it can be called like this:
operator<<(f, 5);
}
This is assuming the operator needs access to gVector3s private data. If not, drop friend and declare it outside the class.

Return value for a << operator function of a custom string class in C++

I am trying to create my own std::string wrapper to extend its functionality.
But I got a problem when declaring the << operator.
Here's my code so far:
my custom string class:
class MyCustomString : private std::string
{
public:
std::string data;
MyCustomString() { data.assign(""); }
MyCustomString(char *value) { data.assign(value); }
void Assign(char *value) { data.assign(value); }
// ...other useful functions
std::string & operator << (const MyCustomString &src) { return this->data; }
};
the main program:
int main()
{
MyCustomString mystring("Hello");
std::cout << mystring; // error C2243: 'type cast' : conversion from 'MyCustomString *' to 'const std::basic_string<_Elem,_Traits,_Ax> &' exists, but is inaccessible
return 0;
}
I wanted cout to treat the class as a std::string, so that I won't need to do something like:
std::cout << mystring.data;
Any kind of help would be appreciated!
Thanks.
Just fyi: my IDE is Microsoft Visual C++ 2008 Express Edition.
If you look at how all stream operators are declared they are of the form:
ostream& operator<<(ostream& out, const someType& val );
Essentially you want your overloaded function to actually do the output operation and then return the new updated stream operator. What I would suggest doing is the following, note that this is a global function, not a member of your class:
ostream& operator<< (ostream& out, const MyCustomString& str )
{
return out << str.data;
}
Note that if your 'data' object was private, which basic OOP says it probably should, you can declare the above operator internally as a 'friend' function. This will allow it to access the private data variable.
You need a free-standing function (friend of your class, if you make your data private as you probably should!)
inline std::ostream & operator<<(std::ostream &o, const MyCustomString&& d)
{
return o << d.data;
}
Firstly, you seem to have an issue with the definition of MyCustomString. It inherits privately from std::string as well as containing an instance of std::string itself. I'd remove one or the other.
Assuming you are implementing a new string class and you want to be able to output it using std::cout, you'll need a cast operator to return the string data which std::cout expects:
operator const char *()
{
return this->data.c_str();
}
That's not how you overload the << operator. You need to pass in a reference to an ostream and return one (so you can stack multiple <<, like std::cout << lol << lol2).
ostream& operator << (ostream& os, const MyCustomString& s);
Then just do this:
ostream& operator << (ostream& os, const MyCustomString& s)
{
return os << s.data;
}