Redefinition of operator << in C++ - c++

I know this question might be stupid, but i am new in C++ and i have a lot of problems with redefinitions of operands.
What i`m trying to do is to redefine the operand << to print my class "Person" information but it appears compiling error:
class Person {
private:
string name;
unsigned long personId;
string address;
public:
Person(string name2,unsigned long id,string adr) {
name = name2;
personId = id;
address = adr;
}
void operator<<(Person person) {
cout<<"Name: "<<person.name<<" Person ID: "<<person.personId<<" Person address: "<<person.address<<endl;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
Person person("Steven",1212121212,"USA");
cout<<person; //compiling error here
return 0;
}
What`s the right way to do this ?

operator << is binary operator, so, first parameter for it should be reference to std::ostream object in your case. Since your variables are private - you cannot overload operator << as free function. First parameter for class function is pointer to object of this class, so you should use friend specificator (which grants access to private variables of your class) on the function.
friend ostream& operator << (ostream& os, const Person& person)
{
os << "Name: "<< person.name << " Person ID: "
<< person.personId << " Person address: " << person.address << endl;
return os;
}

First of all the class definition shall be ended with a semicolon.
class Person {
// ...
};
Secondly you are speaking about overloading an operator not an operand.
Operator << is a binary operator that is applied to two operands. If you want to overload this operator for standard output stream and your class then you should specify as the first parameter standard output stream. Also it is much better to pass an object of your class by const reference. So the declaration will look as
std::ostream & operator <<( std::ostream &os, const Person &person );
That this operator could access data members of your class that are defined as private it should be declared as a friend function of the class or has access to public methods of the class that provide access to private data members.
For example
class Person {
private:
string name;
unsigned long personId;
string address;
friend std::ostream & operator <<( std::ostream &os, const Person &person );
public:
Person(string name2,unsigned long id,string adr) {
name = name2;
personId = id;
address = adr;
};
Or
class Person {
private:
string name;
unsigned long personId;
string address;
ostream & out( std::ostream &os ) const;
public:
Person(string name2,unsigned long id,string adr) {
name = name2;
personId = id;
address = adr;
};
and
std::ostream & operator <<( std::ostream &os, const Person &person )
{
return ( person.out( os ) );
}

Related

Dealing with operator overload method as a friend

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;
}
...
};

How do I access the Private variables of parent class in child Class in C++

Can you take a look at my overladed operator for the package class in my code below. Is it possible to access private variables of the parent class in child class? What I did is I used member functions to write a overloaded operator for the package class but it says "Variable 't' is uninitialized when used here". Go to the end and you will see overladed operator.
#include <iostream>
using namespace std;
// Ticket Class
class Ticket
{
private:
int runTime;
string movieName;
public:
Ticket(int, string);
void setMovieName(string);
void setRunTime(int);
string getMovieName();
int getRunTime();
friend ostream &operator <<(ostream &stream, const Ticket&);
};
// Package Class
class Package : public Ticket
{
private:
string snackName;
public:
Package(int, string, string);
void setSnackName(string);
string getSnackName();
friend ostream &operator <<(ostream &stream, const Package&);
};
int main()
{
}
// Ticket Class empty constructor
Ticket::Ticket(int rnTime, string mvTime) : runTime(rnTime), movieName(mvTime){}
// Ticket Class setter
void Ticket::setMovieName(string mv)
{
movieName = mv;
}
// Ticket class setter
void Ticket::setRunTime(int rn)
{
runTime = rn;
}
// Ticket class getter
string Ticket::getMovieName()
{
return movieName;
}
// Ticket Class getter
int Ticket::getRunTime()
{
return runTime;
}
// Ticket class friend overloaded function
ostream &operator <<(ostream &stream, const Ticket &t)
{
stream << "Movie name: " << t.movieName << endl;
stream << "Run time: " << t.runTime << endl;
return stream;
}
// Child Class empty Constructor
Package::Package(int rnTime, string mvTime, string snTime) : Ticket(rnTime,mvTime), snackName(snTime){}
// Package Class setter
void Package::setSnackName(string sn)
{
snackName = sn;
}
// Package Class Getter
string Package::getSnackName()
{
return snackName;
}
// Package class friend overloaded function
ostream &operator <<(ostream &stream, const Package &p)
{
Ticket *t; // compilers says "Variable 't' is uninitialized when used here"
stream << "Movie: " << t->getMovieName() << endl;
stream << "Run time: " << t->getRunTime() << endl;
stream << "Snack name: " << p.snackName << endl;
return stream;
}
Make your get functions constant, like so:
string getMovieName() const; // <- Note the const specifier
int getRunTime() const; // <- Note it here as well...
Since these functions do nothing more than just return the values... So it is always advisable to do this with all get functions that do not modify the private variables...
And do the same in the definitions as well...
The binary operator<< can simply be defined as:
ostream &operator <<(ostream &stream, const Package &p)
{
stream << "Movie: " << p.getMovieName() << endl;
stream << "Run time: " << p.getRunTime() << endl;
stream << "Snack name: " << p.snackName << endl;
return stream;
}
Note: The reason this works is that the constant const Package &p is a const-qualified parameter... (One that does not allow any modifications inside itself but can be directly assigned from outside, hence the usage of reference operator), and only allows constant member functions (Functions that don't take part in modifying the class members...) to be called from itself... And since we have declared getMovieName() and getRunTime() to be constant functions... They are run correctly...
Note: You should consider visiting here to know more about the different ways how a value can be passed to a parameter of specific type...
You can use the operator<< function defined for the base class in the implementation of the derived class.
ostream &operator <<(ostream &stream, const Package &p)
{
Ticket const& t = p;
stream << t;
stream << "Snack name: " << p.snackName << endl;
return stream;
}
This reduces code duplication and avoids the private member access problem.
When you use public inheritance, all public and protected members of the base class become public and protected in the derived class. In your example, runTime and movieName is private so you can't access it from outside class.
Also, runTime and movieName is already private in Parent. Once declared private, a member always remains private to the base class regardless of the type of inheritance.
To access runTime and movieName change Parent to:
protected:
int runTime;
string movieName;
If you want to access the size member from a derived class, but not from outside the class, then you want protected.
And you should inherit Child by:
class Package : public Ticket

Overloading the Output Stream Operator for a Class

Suppose this is my class:
class Student {
std::string name;
int CWID;
public:
Student(std::string name = "N/A", int CWID = 99999999) : this->name(name), this->CWID(CWID) {}
};
Now, how do I overload the output stream operator << that will print all the data in the class. I'm guessing this is equivalent to the toString() method in Java but kindly show me how to do it in C++.
Add member functions to the class that return the name and CWID.
std::string getName() const {return name;}
int getCWID() const {return CWID;}
Then, add a non-member function to write the data out to a stream.
std::ostream& operator<<(std::ostream& out, Student const& s)
{
return out << s.getName() << " " << s.getCWID();
}
Here is how you do it:
class Student {
std::string name;
int CWID;
public:
Student(std::string name = "N/A", int CWID = 99999999) : name(name), CWID(CWID) {}
friend std::ostream& operator<<(std::ostream& stream, const Student& student);
};
std::ostream& operator<<(std::ostream& stream, const Student& student)
{
stream << '(' << student.name << ", " << student.CWID << ')';
return stream;
}
Please note that this overloaded function is not part of the class.
You could write non-member function
std::ostream& operator<<(std::ostream& os, const Student& stud)
{
os << stud.name << " " << stud.CWID;
return os;
}
and declare it as friend function in your class
class Student {
std::string name;
int CWID;
public:
Student(std::string name = "N/A", int CWID = 99999999) : this->name(name), this->CWID(CWID) {}
friend ostream& operator<<(ostream& os, const Student& stud);
};

c++ overloading operator<< and operator>>

class Book
{
string title;
int category;
public:
Book(const string& abook, int num);
string getTitle() const;
int getCategory() const;
friend ostream& operator<<(ostream& os, const Book& abook);
friend istream& operator>>(istream& is, Book& abook);
};
class Reader // base class
{
private:
string reader_name;
vector<Book> bookLists;
public:
string showname() const;
void add(const Book& abook); // organize book list
friend ostream& operator<<(ostream& os, const Reader& read_name);
friend istream& operator>>(istream& is, Reader& read_name);
};
class fantasyReader : public Reader { };
class horrorReader : public Reader { };
class scienceReader : public Reader { } ;
class mysteryReader : public Reader { };
I have two given text files.
1) Reader.txt <--- contains reader's name and category
For ex.
David <- reader's name
0 <- david is Fantasy reader
2) Book.txt <---- contains Book's title and category
For ex
Riddick <- Book's title
0 <- Book's category is fantasy
In the main function, array of pointers to Reader's obj are pointing each dervied class;
ex
Reader *obj[10];
int pos =0;
obj[pos++] = new fantasyReader();
The main goal is to organize book's list and put into a appropriate category and appropriate reader and write them into a new text file.
ex.
-David-
Riddick
-John-
The Crow
MY QUESTION
I'm not sure what should be inside of operator<< and operator>>
for class Book and class Reader
What should you put inside the overloaded << and >> operators?
Well, You can actually put anything inside the overloaded << and >> operator. They will just be simple function calls whenever a appropriate opportunity presents.
For eg:
Book obj;
cout<< obj; //Calls your overloaded << operator
As a general principle while overloading operators you should follow Principle of Least Astonishment, which means your code should be doing something similar what the operator does for a intrinsic data type. In the above example I would expect my << operator to display the contents of my Book class, in that case I would overload it as follows:
// Display title and category
ostream& operator<<(ostream& os, const Book& abook);
{
os << abook.title << "\n";
os << abook.category<< "\n";
return os; // must return ostream object
}
I need to return a stream object since it allows for the chaining ex:
Book obj1,obj2,obj3;
cout<<obj1<<obj2<<obj3;
Similarly, for >> Extraction operator I would expect the operator to get the data from user.
For ex:
Book obj;
cin>>obj; //Calls your overloaded >> operator
I would overload the >> operator as follows:
//Get the Book Title & Category from User
istream& operator>>(istream& is, Book& abook)
{
cout << "Enter Book Title: ";
is >> abook.title ;
cout << "Enter Book Category: ";
is >> abook.category;
return is; //Must return stream object
}
So, the bottomline is You can put any functionality inside >> and << operators but don't forget the Principle of Least Astonishment!

C++ Overloading << Operator problem

I'm fairly noobish at C++, but very comfortable with pointers, dereferencing, etc. I'm having a problem with my overload of the << operator for a class, in that it compiles fine but crashes when run. It feels like an infinite loop, but I'm not certain. Here's the code, and any help is appreciated.
#include <string>
#include <iostream>
using namespace std;
class Person
{
private:
string _name;
Person* _manager;
public:
Person(string name, Person *manager);
Person(string name);
friend ostream &operator<<(ostream &stream, Person &p);
};
Person::Person(string name, Person *manager)
{
_name = name;
_manager = manager;
}
Person::Person(string name)
{
_name = name;
}
ostream &operator<<(ostream &stream, Person &p)
{
Person* mgr = p._manager;
stream << p._name << std::endl;
stream << mgr->_name << std::endl;
return stream;
}
int main()
{
Person *pEmployee = new Person("John Doe Employee");
Person *pManager = new Person("John Doe Manager", pEmployee);
cout << *pEmployee;
cout << *pManager;
return 0;
}
In your constructor with just a single argument, you need to set _manager to NULL/0. Test for this in your operator<< and don't output mgr->name if it is NULL/0. As it stands, you are dereferencing an uninitialised pointer.
Person::Person(string name)
{
_name = name;
_manager = 0;
}
ostream &operator<<(ostream &stream, Person &p)
{
Person* mgr = p._manager;
stream << p._name << std::endl;
if (mgr)
stream << mgr->_name << std::endl;
return stream;
}
There are a number of other things you could do better, such as using const references on arguments and using the constructor initialiser list, but they wont be the cause of your problem. You should also address ownership issues with the manager object you pass in to the constructor to ensure it does not get double-deleted.
your _manager pointer is not initialized upon constructing the first Person instance, hence referencing p._manager in your operator << crashes.
Besides that, you have a memory leak since you call new but not delete.
Your implementation of operator<< does not check if the _manager member is valid. If there is no manager, you should make this explicit by setting the pointer to 0. Otherwise the pointer value is undefined and accessing it will crash your program.
(1) Your Person class should set _manager to 0 (null pointer) if none is supplied in the constructor:
Person::Person(string name) : _name(name), _manager(0)
{
}
(2) In your operator<<, check the pointer before dereferencing it:
if (mgr) {
stream << mgr->_name << std::endl;
}
Some hints for better code:
(1) Change your function arguments to accept const string& instead of string. This way, the string is not copied when calling the function/constructor, but passed as a constant reference.
(2) It is cleaner to let your operator<< accept a const reference for the Person as well, since it does not/should not modify the Person. This way, you can use the operator also in places where you have a constant Person.
Person::Person(string name)
{
_name = name;
}
Who is your manager?
Person::Person(string name) : _manager(NULL)
{
_name = name;
}
ostream &operator<<(ostream &stream, Person &p)
{
Person* mgr = p._manager;
stream << p._name << std::endl;
if (mgr != NULL) { stream << mgr->_name << std::endl; }
return stream;
}
Your Person instance *pEmployee does not have the _manager set. This may be a NULL pointer.