How to call overloading functions from the base class (not abstract)? - c++

Class DVD inherits class Media, has one more variable than the base class does.
I declare a pointer:
Media* ptr = new DVD(...);
I want to print out the content of the DVD, so the following code works as expected:
ptr->print(cout);
But using the overloaded << operator only invokes the base class print() function:
cout << *ptr << endl;
So it prints out only the ID, not with the name of the director.
One way to solve this problem is to modify the overload << operator a bit to make it accept pointers, so:
cout << ptr << endl;
should work, but somehow I must find the way to make cout << *ptr << endl; work as expected.
Any advice?
The thing is I can't make the base class (Media) abstract because I need to call an instance of it in the overloading ostream operator, so a pointer of the base class can not invoke the overloading function of the derived class, which it's pointing to.
Code:
#include <iostream>
using namespace std;
class Media{
private:
int id;
public:
Media(int _id) : id(_id) {}
virtual ~Media();
virtual void print(ostream &out);
friend ostream& operator << (ostream& out, Media aMedia);
};
Media::~Media(){}
class DVD : public Media {
private:
string director;
public:
DVD(int _id, string _director = "unknown") : Media(_id), director(_director) {}
~DVD();
void print(ostream &out);
};
DVD::~DVD(){}
void Media::print(ostream& out){
out << "ID " << id;
}
void DVD::print(ostream& out){
out << "DVD: ";
Media::print(out);
out << " Directed by " << director;
}
ostream& operator << (ostream& out, Media aMedia){
aMedia.print(out);
return out;
}
int main() {
Media *ptr = new DVD(352, "Stephen Spielberg");
ptr->print(cout); // Prints out: "DVD: ID 352 Directed by Stephen Spielberg". Correct!
cout << endl;
cout << *ptr << endl; //Prints out: "ID 352" Incorrect!
}

Problem is in this declaration ostream& operator << (ostream& out, Media aMedia). You are accepting the parameter aMedia by copy which causes object slicing, accept it by using a reference by changing the signature to ostream& operator << (ostream& out, const Media& aMedia) .
Because of the slice when you do cout << *ptr , a copy of the DVD is created of type Media (i.e. DVD is sliced to a Media), now when you call print since the type of the object is Media call goes to the Media::print. You can read more about object slicing here.

Or pass aMedia by reference Media& to << so that virtual dispatching will occur.
You're passing a Media object directly, which means a new copy of the DVD object will be created, and the DVD only parts will be thrown away and just the Media parts of it will be end up in the aMedia parameter.
see:
ostream& operator << (ostream& out, const Media& aMedia){
aMedia.print(out);
return out;
}

Related

c++ overloaded << prints adress of object attribute, instead of actual value

So I am learning operation overloading.
I am trying to overload << to print object properties.
In my case Properties is a class that inherits the public section of the person class.
This is what i have:
class Person {
private:
string name;
int egn;
string adress;
public:
friend ostream& operator << (ostream& out, const Person& c);
}
ostream& operator << (ostream& out, const Person& c)
{
out << "Person name: " << c.name << "\n" << "Person egn: " << c.egn;
return out;
}
int main()
{
Properties* person_obj_1 = new Properties();
person_obj_1 = add_person(person_obj_1);//Add some values
cout << person_obj_1 << "\n";
}
And the output I get is 000001CE89252130. This is not what I want. I need to print the actual values of my attributes. What am I doing wrong?
What am I doing wrong?
You're printing a Properties* instead of a Person object. That is, to get your expected result you need to use cout on a Person object for which you've overloaded operator<< instead of Properties* which is a pointer.

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

Can operator<< in derived class call another operator<< in base class in c++?

In my code, Manager is derived from Employee and each of them have an operator<< override.
class Employee{
protected:
int salary;
int rank;
public:
int getSalary()const{return salary;}
int getRank()const{return rank;}
Employee(int s, int r):salary(s), rank(r){};
};
ostream& operator<< (ostream& out, Employee& e){
out << "Salary: " << e.getSalary() << " Rank: " << e.getRank() << endl;
return out;
}
class Manager: public Employee{
public:
Manager(int s, int r): Employee(s, r){};
};
ostream& operator<< (ostream& out, Manager& m){
out << "Manager: ";
cout << (Employee)m << endl; //can not compile, how to call function of Employee?
return out;
}
I hoped cout << (Employee)m << endl; would call ostream& operator<< (ostream& out, Employee& e), but it failed.
Cast to a reference instead of a copy:
cout << (Employee&)m << endl; //can not compile, how to call function of Employee?
Also note the ostream operator is in no way member of the class(it seems you are confused about that from the title of the question).
Change cout << (Employee)m << endl; to cout << (Employee&)m << endl;.
The explanation of the error message is this:
When you attempt the cast (Employee)m, you are creating a temporary. The operator<< overload takes a reference. You cannot take a reference to a temporary.
Since you really just want it to print it's own data (not make a copy of itself), you cast the reference you have to the reference of the type you need (it's base class).
As jrok pointed out in his answer, you can also accomplish this by providing a virtual function to print the data. That would be a simpler approach as it would not require you to overload operator<< for every derived class.
The usual way of doing this is to have (a possibly private or protected) virtual print (or any other suitable name) function in the base class that derived classes can override.
You only provide general operator<< for a reference to the base class and call print inside it. The overriding print functions can call the base's print, if need be.
Your overload:
ostream& operator<< (ostream& out, Employee& e)
only works for references to Employee objects, so it won't work on non-reference values (like the result of a cast).
Normally, the prototype would be:
ostream& operator<< (ostream& out, const Employee& e)
which also provides the reassurance that printing an Employee doesn't mutate it. If you change that, things should work just fine. (ostream& does have to be a reference, not a const reference, because the ostream is mutated by the print operation.)
There are two problems which combined make your compilation to fail.
(1) This declaration and definition:
ostream& operator<< (ostream& out, Employee& e){
out << "Salary: " << e.getSalary() << " Rank: " << e.getRank() << endl;
return out;
}
Despite you don't change e, you take it reference to non-const. This forbids you calling this operator on an rvalue.
(2) This line
cout << (Employee)m << endl;
As said by others you are slicing m. In addition, the cast (Employee) m returns a temporary Employee which is an rvalue.
In summary, the cast (Employee)m yields an rvalue which cannot bind to e.
You can fix either one or the other to make your code compiler but it's better to fix both problems to make your code more robust:
// ...
ostream& operator<< (ostream& out, const Employee& e) {
// ...
// ...
cout << static_cast<Employee&>(m) << endl;
// ...
First, you overload a global function. This is another concept than overriding. see Override and overload in C++
Next, your cast is wrong. This should do:
ostream& operator<< (ostream& out, Manager& m){
out << "Manager: ";
cout << static_cast<Employee&>(m) << endl; //can not compile, [...]?
return out;
}
...if you really want to overload the global << operator.

Given a base class as a parameter, how do I use op<< overload to print the characteristics of a derived class if one is passed?

This is for a homework assignment.
I have a base class Item and a derived class Book.
I have op<< overloaded in Item class:
ostream& operator<<(ostream& out, const Item* const item)
{
out << item->getName() << endl;
return out;
}
As well as in Book class:
ostream& operator<<(ostream& out, const Book* const b)
{
out << b->getPages() << endl;
return out;
}
However only the Item operator is used when I run my code, and it does not print the pages for a book. I have made sure that a "book" gets printed, not just the base class. From the material I've read it seems that overloading the operators for both the base and derived classes is what you're supposed to do, so I'm not sure why my book info doesn't get printed.
You can use polymorphism instead of overloading: add a virtual print method to the classes:
class Item
{
public:
virtual void print(std::ostream& o) const
{
out << getName() << endl;
}
....
};
class Book : public Item
{
public:
virtual void print(std::ostream& o) const
{
out << getPages() << endl;
}
....
};
then use a single ostream& operator<<:
ostream& operator<<(ostream& out, const Item& item)
{
item.print(out);
return out;
}
then
Item* i1 = new Item(....);
Item* i2 = new Book(....);
std::cout << *i1 << " " << *i2 << std::endl;
delete i1;
delete i2;
If you change the derived class function's signature, it's no longer an override of the base class member function.
"However only the Item operator is used when I run my code" - this behaviour might be because you apply it to the pointer*/reference& on the base class;
If you have a container in which you want to store instances of different classes what are derived from the same base class and apply to all of them operator<<, which behaviour will depend on the class of instance for each it is invoked, you have to make sure that:
1.There is at least one virtual method in you base class (this will cause compiler to generate
virtual table for that class and later this table can be used by operator dynamic_cast)
2. Enable RTTI (run-time type identification) in your project : project/c++/language enable RTTI support
3. implement operator<< using the following idea:
ostream& operator<<(ostream& out, const Item& item)
{
if (Book* pBook = dynamic_cast<Book*>(&item)
{
out << pBook ->getName() << endl;
}
if (OtherDerivedClassName* pOtherDerivedClass = dynamic_cast<OtherDerivedClassName*>(&item)
{
// do other interesting things
}
return out;
}

C++: friend function, derived class

I've got 2 classes, base class is "Port" and derived class is "VintagePort".
As far as I know If i use reference or pointer of base class to object of derived class, it automatically finds correct method, not for reference or pointer but exactly to object(if methods are virtual).
In my situation you can see both classes have friend function "operator<<". But it looks like when I'm using pointer for base class, it calls function only from base class. If I use "cout << VintagePort" It works ok.
My question: Is it working correctly or I should fix something in code?
std::ostream& operator<<(std::ostream& os, const Port& p)
{
os << p.brand << ", " << p.style << ", " << p.bottles << endl;
return os;
}
std::ostream& operator<<(std::ostream& os, const VintagePort& vp)
{
os << (const Port &) vp;
cout << ", " << vp.nickname << ", " << vp.year << endl;
return os;
}
VintagePort vp1;
VintagePort vp2("Gallo", "lekko brazowy", 50, "Blaze", 1990);
VintagePort vp3(vp2);
Port* arr[3];
arr[0] = &vp1;
arr[1] = &vp2;
arr[2] = &vp3;
for (int i = 0; i < 3; i++)
{
cout << ">>>>> " << i+1 << " <<<<<" << endl;
cout << *arr[i]; // call for base class instead derived class
arr[i]->Show();
}
The compiler doesn't now the pointer actually points to an inherited class. One way to solve this is to have a virtual function in the base class for output, and override it in the class inheriting the base class. Then call this virtual method in the output operator.
In C++ polymorphism can only be achieved by means of virtual functions, and operator<< is not one (and cannot be for your purposes, since the first argument is the std::ostream. If you need this sort of behavior, the simple approach is providing a virtual print function in your hierarchy, and have operator<< forward the call performing dynamic dispatch:
struct base { // Don't forget virtual destructors
virtual void print( std::ostream& ) const;
};
struct derived : base {
virtual void print( std::ostream& ) const;
};
std::ostream& operator<<( std::ostream& o, const base& b ) {
b.print( o );
return o;
}