I have two classes, base and derived. In main I have a vector which is *base type and contains one base object and one derived object. I have overloaded output operator for both classes, but when I print the vector for derived class, base output operator is called although I have overloaded it separately. What should I change in my program to change output from:
12
30
to
12
30 31
?
This is the code:
#include <iostream>
#include <vector>
using namespace std;
class base {
int x;
public:
base(int _x) : x(_x) {}
friend ostream& operator<<(ostream& out, base obj) {
return out << obj.x;
}
};
class derived : public base {
int y;
public:
derived(int _x, int _y) : base(_x), y(_y) {}
friend ostream& operator<<(ostream& out, derived obj) {
return out << (base) obj << ' ' << obj.y;
}
};
int main() {
vector<base*> vec;
base* a = new base(12);
derived* b = new derived(30,31);
vec.push_back(a);
vec.push_back(b);
for (auto p: vec) cout << *p << '\n';
}
Dynamic dispatch, based on the underlying object, works only for virtual member functions. It does not work for non-member functions or non-virtual member functions.
One way to get around the problem would be:
Use the friend function using the base type.
Change the argument type for obj to be a const reference.
From that function, call a virtual member function to do the real work.
class base {
int x;
public:
base(int _x) : x(_x) {}
virtual std::ostream& write(std::ostream& out) const
{
return (out << x);
}
// Change obj to be a const reference
friend std::ostream& operator<<(std::ostream& out, base const& obj)
{
return obj.write(out);
}
};
class derived : public base {
int y;
public:
derived(int _x, int _y) : base(_x), y(_y) {}
virtual std::ostream& write(std::ostream& out) const
{
// Let the base class take care of its part.
base::write(out);
// Now take care of this class part.
return ( out << ' ' << y);
}
// This is useless now.
// friend ostream& operator<<(ostream& out, derived obj) {
// return out << (base) obj << ' ' << obj.y;
// }
};
PS Why is "using namespace std;" considered bad practice?
Related
I'm currently new to OOP concepts of C++ language like friend of the function and friend of the class .
May be this is not he best comparision between freinds and getters but for the example below:
#include <iostream>
using namespace std;
class ClassB; // forward declaration
class ClassA
{
int numA;
friend int add(ClassA, ClassB); // friend function declaration
public:
ClassA() : numA{12} {} // constructor to initialize numA to 12
};
class ClassB
{
int numB;
friend int add(ClassA, ClassB); // friend function declaration
public:
ClassB() : numB(1) {}
};
// access members of both classes
int add(ClassA objectA, ClassB objectB)
{
return objectA.numA + objectB.numB;
}
int main()
{
ClassA objectA;
ClassB objectB;
cout << "Sum: " << add(objectA, objectB);
return 0;
}
what if i simply use getter to get the values and add them. The main moto of friend function is to access the private and public data members (i guess) , and getters are already doing this .
I'm quite confused here.
There is an excellent talk about this subject here: CppCon 2017: Klaus Iglberger “Free Your Functions!”
My take-away is that if a member function needs no access to the internals of a class, then it should not be a member function. In your case, how will Class A be usable? It is not right now, but I imagine you will have something like explicit operator int() const or int get_val() const. You can simply use this in a free function:
A operator+(A lhs, B rhs) {
return A{lhs.get() + rhs.get()};
}
B operator+(B lhs, A rhs) {
return B{lhs.get() + rhs.get()};
}
int main() {
...
cout << "sum: " << (objectA + objectB).get() << "\n";
...
Or something similar.
This question already has answers here:
Templates and overloadering operator << [duplicate]
(5 answers)
Closed 7 years ago.
I'm trying to implement a sort of virtual operator << that lets me send a IBase class object to cout so that it calls the Derived class' operator <<. Is this possible?
class IBase
{
public:
IBase() {};
virtual ~IBase() {};
};
template <typename T>
class Derived
: public IBase
{
public:
Derived(T data);
template <typename U>
friend std::ostream& operator<<(std::ostream& os, const Derived<U>& dt);
private:
T data_;
};
template <typename T>
Derived<T>::Derived(T data)
: IBase(),
data_(data)
{
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const Derived<T>& dt)
{
os << dt.data_;
return os;
}
int _tmain(int argc, _TCHAR* argv[])
{
IBase* base = new Derived<int>(5);
std::cout << *base;
}
The << operator is a function, not a method and thus it can not be virtual. However you can still achieve what you want- remember that the operator<< takes a reference as parameter? Well polymorphism works on those too. Simply add another virtual method that you call from the << operator.
Have a look at this short example I put together:
#include <iostream>
#include <string>
using namespace std;
class Base {
public:
virtual string toString() const {
return "base";
}
};
class Child : public Base {
public:
virtual string toString() const {
return "child";
}
friend ostream& operator<<(ostream& out, const Base& b);
};
ostream& operator<<(ostream& out, const Base& b) {
out << b.toString();
return out;
}
int main() {
Child c;
cout << c;
return 0;
}
And here is a link in ideone: http://ideone.com/EmP1oP
Your goal can't be attained through templates alone as dereferencing a IBase* gets you a IBase& - template instantiation occurs at compile time and the compiler has no access to the runtime type.
(Dynamic dispatch only happens when you invoke a member function of an object, and a binary operator can't be a member of its right-hand operand.)
So your templated operator will never be used if you pass a dereferenced IBase* to operator <<.
Instead, add a virtual output function to the base and override it:
class IBase
{
public:
IBase() {};
virtual ~IBase() {};
virtual std::ostream& output(std::ostream&) const = 0;
};
template <typename T>
class Derived
: public IBase
{
public:
Derived(T data);
virtual std::ostream& output(std::ostream& os) const
{
os << data;
return os;
}
private:
T data_;
};
std::ostream& operator<<(std::ostream& os, const IBase& dt)
{
return dt.output(os);
}
You can make it virtual for real with a help of simple template rig (which, in addition, does not prevent de-virtualization).
struct X {
virtual std::ostream& repr(std::ostream& out) const;
}
template <class X>
std::enable_if_t<
std::is_same<
std::void_t<
decltype(std::declval<X>().repr(std::declval<std::ostream>()))>,
void>::value,
std::ostream&>
operator<<(X const& x)
{
return x.repr(out);
}
I have the following problem.
I've created an array of pointers to objects from the base class, but I'm storing in this array also the pointers to the objects from the derived classes.
I also overloaded the <<operator in each class to display the objects.
However, when I apply this overloaded <<operator to the above mentioned array, it treats all the pointers as if there were pointing to the objects of the base class.
Below I present the code that depicts the problem.
I need this overloaded operator to work correctly because I need to save the objects pointed by the array in the file.
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
class Base
{
public:
int basevar;
Base(): basevar(1) {};
virtual void dosth(){};
friend ostream & operator<<(ostream & screen, const Base & obj);
};
ostream & operator<<(ostream & screen, const Base & obj)
{
screen << obj.basevar;
return screen;
};
class Der1: public Base
{
public:
int de1;
Der1(): de1(2) {};
virtual void dosth()
{
cout << "Der1" << endl;
}
friend ostream & operator<<(ostream & screen, const Der1 & obj);
};
ostream & operator<<(ostream & screen, const Der1 & obj)
{
Base b;
b = static_cast <Base>(obj);
screen << b;
screen << " " << obj.de1;
return screen;
};
class Der2: public Base
{
public:
int de2;
Der2(): de2(3) {};
virtual void dosth()
{
cout << "Der2" << endl;
}
friend ostream & operator<<(ostream & screen, const Der2 & obj);
};
ostream & operator<<(ostream & screen, const Der2 & obj)
{
Base b;
b = static_cast <Base>(obj);
screen << b;
screen << " " << obj.de2;
return screen;
}
int main()
{
Base * array[] = {new Base(), new Der1(), new Der2()};
for(int i=0; i<3; ++i)
{
cout << *array[i]; // <- always displays objects as if they were from the base class
}
return 0;
}
You can declare a virtual function in the base class the following way
class Base
{
public:
int basevar;
Base(): basevar(1) {};
virtual std::ostream & out( std::ostream &os ) const
{
return os << basevar;
}
virtual void dosth(){};
friend ostream & operator<<(ostream & screen, const Base & obj);
};
In this case the operator will look like
ostream & operator<<(ostream & screen, const Base & obj)
{
return obj.out( screen );
};
and in derived classes redefine the virtual function. For example
class Der1: public Base
{
public:
int de1;
Der1(): de1(2) {};
std::ostream & out( std::ostream &os ) const
{
return Base::out( os ) << " " << obj.de1;
}
virtual void dosth()
{
cout << "Der1" << endl;
}
};
In this case there is no need to define the operator for derived classes.
class Vehicle{
long Number;
int Year;
char *Make,*Model,*BodyStyle,*Color;
float Cost;
friend ostream & operator<<(ostream& stream,const Vehicle& v);
class TruckVehicle:public Vehicle{
int Passengers;
long Mileage,GrossWeight,TempGross;
char *PoweredBy;
friend ostream & operator<<(ostream& stream,const TruckVehicle& t )
in the above code ..how do i call the overloaded << of the base class to the << function of derived class??
replies will be highly appreciated.
Simplest and cleanest way to do this is:-
class Base
{
public:
virtual ostream& put(ostream& s) const = 0;
};
ostream& operator<<(ostream& s, const Base& r)
{
return r.put(s);
}
class Derived : public Base
{
public:
ostream& put(ostream& s) const;
};
void f(const Base b, Derived d)
{
cout << b << d;
}
i.e put() is a virtual function that ensures that the right output operation is used in <<.
Is this the only way of overloading the ostream& operator<< for a derived class without duplicating code for the base class? Are the casts not something to be avoided?
I don't see any other way, except to define some kind of function in the base class that will represent the data of the base class as something that std::operator<< could "eat up" (like a string?), doing the same thing for the derived class (calling the base class stream representation function within the derived class stream. rep. function of course).
What is the ideal solution to this problem?
#include <iostream>
class Base
{
private:
int b_;
public:
Base()
:
b_()
{};
Base (int b)
:
b_(b)
{};
friend std::ostream& operator<<(std::ostream& os, const Base& b);
};
std::ostream& operator<< (std::ostream& os, const Base& b)
{
os << b.b_;
return os;
}
class Derived
:
public Base
{
private:
int d_;
public:
Derived()
:
d_()
{};
Derived (int b, int d)
:
Base(b),
d_(d)
{};
friend std::ostream& operator<<(std::ostream& os, const Derived& b);
};
std::ostream& operator<< (std::ostream& os, const Derived& b)
{
os << static_cast<const Base&>(b) << " " << b.d_;
return os;
}
using namespace std;
int main(int argc, const char *argv[])
{
Base b(4);
cout << b << endl;
Derived d(4,5);
cout << d << endl;
return 0;
}
Well ... casting should be avoided if done in contexts where the result is not correctly defined, but casting into a base is always safe.
It is possible to avoid the explicit cast by considering that a derived reference decays into the base reference, so you can use an implicit conversion, like in this case:
std::ostream& operator<< (std::ostream& os, const Derived& b)
{
const Base& bs = b;
os << bs << " " << b.d_;
return os;
}
static_cast<const Base&>(b)
is safe and there is nothing incorrect, because every derived class object is also an Base class object and can be treated like one.
Casts are dangerous only when used in a reckless way, You must use casts where they are needed and in a correct manner, that is the very purpose of their provision by the language standard.
If you don't like the casts, you can have your operator call a writeTo function that is implemented using the template method pattern.
e.g.
class Base {
public:
std::ostream& writeTo(std::ostream& ostr) const { os << b_; return this->doWriteTo(os); }
private:
int b_;
virtual std::ostream& doWriteTo(std::ostream& ostr) const = 0; // pure virtual
};
class Derived {
private:
int d_;
virtual std::ostream& doWriteTo(std::ostream& ostr) const {return ostr << d_;}
};
std::ostream& operator<<(std::ostream& ostr, const Derived& d) {
return d.writeTo(ostr);
}
Actually, using this pattern, you can write operator<< once and for all for Base:
std::ostream& operator<<(std::ostream& ostr, const Base& b) {
return b.writeTo(ostr);
}
This pattern also elminates the need to make operator<< a friend.
You could change things around like this:
struct Base {
int b_;
void print(ostream &o) { o << b_; }
};
struct Derived : Base {
int d_;
void print(ostream &o) {
Base::print(o);
o << ' ' << d_;
}
};
ostream &operator<<(ostream &o, Base &b) {
b.print(o);
return o;
}
ostream &operator<<(ostream &o, Derived &d) {
d.print(o);
return o;
}
If Base had virtual functions (which in this example it doesn't), then print could be one of them, and you could get rid of the multiple overloads of operator<<.