C++: friend function, derived class - c++

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

Related

How to properly define and call original operator<<

Consider the following example:
#include <iostream>
class A {
const int i;
const int j;
public:
A(int i_, int j_) : i(i_), j(j_) {}
std::ostream& operator<<(std::ostream& o) const {
o << "i is " << i << ", j is " << j;
return o;
}
};
std::ostream& operator<<(std::ostream& o, const A& a ) {
o << "This is A: ";
a.operator<<(o);
return o;
}
int main() {
A a(0,42);
std::cout << a << std::endl;
return 0;
}
It will generate the following output:
This is A: i is 0, j is 42
The output is correct but I don't like how I am calling A's original operator<<.
I am trying to figure out how to properly define that operator, so it could be called this way:
o << "This is A: " << (some magic)a;
instead of
o << "This is A: ";
a.operator<<(o);
I have tried various ways but either I get to ambiguity issues or getting an address of the std::cout and broken string. Notice that the result std::ostream& of A::operator<< is a remnant of my tests. In the example above it would suffice to use void.
Is it possible without creating an intermediate class B that derives from class A and defines its own operator<< (class NiceOutputOfA : public A {...};) ?
Binary operators defined in-class always have the class as the left-hand side operand. Which means you cannot implement stream insertion/extraction in-class.
Probably the most common way is to implement the operator as a friend defined inline in the class.
Another reasonably common way is to provide a named streaming function in the class, and an out-of-class streaming operator which calls that function. You almost did that, but named that function operator <<.
The closest resolution I came to is by creating an intermediate class:
class Decorate {
const A& a;
public:
Decorate(const A& a_) : a(a_) {}
friend std::ostream& operator<<(std::ostream& o, const PrintA& pa) {
o << "This is A: " << pa.a;
return o;
}
};
and having it printed this way:
int main() {
A a(0,42);
std::cout << Decorate(a) << std::endl;
return 0;
}
I was looking for something prettier but based on Angew's answer I lost hope to have it done suing proper operator<< declaration.
Thanks for all your help!
Marking Angew's response as the answer.

C++ - Object slicing even after using pointers

I have a base class Shape, and a derived class Circle which inherits Shape publically:
class Circle : public Shape
I made a C++ vector of Shape pointers, and I assigned Circle pointers to them. I'd read up a lot on object slicing so expected the code to treat the Circle in the vector as a Circle, not a Shape.
Can anyone point out what's wrong with this, given the output?
int main(void) {
vector<Shape*> shapes;
Circle* ncl = new Circle(-8, -8, 0.2f);
shapes.push_back(ncl);
cout << "Expected: " << *ncl << endl;
cout << "Reality: " << *shapes[0] << endl;
}
outputs:
Expected: Circle is at: -8,-8 and has a radius of: 0.2
Reality: Shape centered at point: -8,-8
I have overridden the << operator for both classes out of scope, so I think that's not the problem, but still - here's the code context of my overrides:
inline std::ostream& operator<< (std::ostream& stream, const Shape& shape) {
std::cout << "Shape centered at point: " << shape.getX() << "," << shape.getY();
return stream;
}
inline std::ostream& operator<< (std::ostream& stream, const Circle& circle) {
std::cout << "Circle is at: " << circle.getX() << "," << circle.getY() <<
" and has a radius of: " << circle.getR();
return stream;
}
All in all - I want to be able to access my Circle variables properly while they're stored in the Shape vector (with pointers or otherwise).
There's no slicing involved, it just looks like it.
Overloads are selected at compile time, from the static type as it is known to the compiler.
Since shapes is a vector<Shape*>, *shapes[0] is a Shape&, and that overload is chosen.
The common solution is to only write an operator<< for the base class, and that in turn calls a virtual function on the object.
This will let the dynamic function dispatch select the function at runtime.
For instance:
struct Shape { virtual ostream& print(ostream& os) const { ... } };
struct Circle { ostream& print(ostream& os) const override { ... } };
ostream& operator<<(ostream& os, const Shape& s) { return s.print(os); }
overload resolution is done with static type.
You may use:
std::ostream& operator<< (std::ostream& stream, const Shape& shape) {
shape.print(stream);
return stream;
}
with virtual void Shape::print(std::ostream&) const; to solve your issue.

How to make the streaming operator of the derived class also output the base class

Let's say I have a class called dogs and inherited from that, a class called shepherd, now I overload the streaming operator for my base class but now when I overload the streaming operator for my derived class I would like it to also output the variables that were originally from my base class.
Obviously I could copy paste the code used for overloading the base class streaming operator, but I was looking for a more elegant solution that didn't involve copying large amounts of code (especially since the real example has a lot more variables inside the base class).
an example.
class Dogs
{
public:
int N_legs;
bool hair_short;
};
class Shepherd : public Dogs
{
public:
bool guarding;
};
std::ostream &operator<<(std::ostream &os, Dogs dogs)
{
os << "the content of class dogs" << std::endl;
os << dogs.N_legs << "\t" << dogs.hair_short << std::endl;
return os;
}
Now I tried a dynamic cast but that didn't work.
std::ostream &operator<<(std::ostream &os, Shepherd shepherd)
{
os << dynamic_cast<Dogs>(shepherd);
os << "The content of class shepherd" << std::endl;
os << shepherd.guarding << std::endl;
return os;
};
somewhere in main
Dogs dogs;
dogs.N_legs = 4;
dogs.hair_short = true;
std::cout << dogs << std::endl;
Shepherd shepherd;
shepherd.N_legs = 4;
shepherd.guarding = true;
std::cout << shepherd << std::endl;
Now this will give me an output that only consists of the derived class variables (when you comment out the dynamic cast) but I would also like to have the contents of the base class.
dyanamic_cast only works with references and pointers, that's why your code can't compile. You should change the parameter type to const &, not only for fixing the error, also for avoiding unnecessary copy.
std::ostream &operator<<(std::ostream &os, const Dogs& dogs)
std::ostream &operator<<(std::ostream &os, const Shepherd& shepherd)
{
os << dynamic_cast<const Dogs&>(shepherd);
...
BTW: For this case static_cast will be sufficient.
dynamic_cast is not required here, as you always know that Dogs is a base class of Shepherd. Simply use static_cast:
std::ostream &operator<<(std::ostream &os, const Shepherd& shepherd)
{
os << static_cast<const Dogs&>(sheperd);
os << "The content of class shepherd" << std::endl;
os << shepherd.guarding << std::endl;
return os;
};
Use static_cast instead; you know the base-type at compile-time!
std::ostream &operator<<(std::ostream &os, Shepherd shepherd) {
os << static_cast<Dogs>(shepherd);
os << "The content of class shepherd" << std::endl;
os << shepherd.guarding << std::endl;
return os;
}
Here's a Wandbox link.

Operator << overload inheritance, why I got input from base class, instead of child class?

I have a class, let's call it A, it has only one field, aa. I have another class, B, which inherits class A, and instead of having the aa field, it also has its own field, bb. Now, I overloaded operator << (cout) for both classes. I tried to use polimorphism, but it seems that polimorphism does not work properly with operators. My code shows me only aa field when using operator cout for showing the object obj.
I mean, do I always need to add the virtual word to overload the function from the base class in a child class? If so, how should I do the same with operators, operators can't be virtual ...
#include <iostream>
#include <ostream>
using namespace std;
class A
{
protected :
int aa;
public:
A(int aa) {this->aa = aa;}
~A(){}
friend ostream &operator<<(ostream &os, const A& obj);
virtual void show() {cout << "a = " << aa << "\n"; }
};
ostream &operator<<(ostream &os, const A& obj)
{
for(int i=0; i<80; i++)
os << "-";
os << "\n";
os << "a = " << obj.aa << "\n";
for(int i=0; i<80; i++)
os << "-";
os << "\n";
return os;
}
class B : public A
{
private :
int bb;
public:
B(int aa, int bb) : A(aa) {this->bb = bb;}
~B(){}
friend ostream &operator<<(ostream &os, const B& obj);
void show() {cout << "a = " << aa << "\n"; cout << "b = " << bb << "\n";}
};
ostream &operator<<(ostream &os, const B& obj)
{
for(int i=0; i<80; i++)
os << "-";
os << "\n";
os << "a = " << obj.aa << "\n";
os << "b = " << obj.bb << "\n";
for(int i=0; i<80; i++)
os << "-";
os << "\n";
return os;
}
int main()
{
A *obj = new B(2,3);
cout << *obj;
obj->show();
delete obj;
return 0;
}
I mean, do I always need to add the virtual word to overload the function from the base class in a child class? If so, how should I do the same with operators, operators can't be virtual ...
Sure they can. But only member functions can be virtual, and these operators are not members functions - they're global functions.
In this case, you can't make them member functions (because the first parameter isn't an instance of your class). But you could create a virtual member function and have the operator call it:
class A
{
protected:
virtual void print(ostream &);
public:
friend ostream &operator<<(ostream &os, const A& obj);
// ... other stuff ...
};
ostream &operator<<(ostream &os, const A& obj)
{
obj.print(os);
return os;
}
and then override print instead of 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;
}