As you can see, only the overloaded version of the stream insertion operator for the base class is called on both instances. I understand why it's so. It's because there is no dynamic binding. But, how do I fix it?
#include <iostream>
using namespace std;
class A {
int i;
char c;
public:
A(int i = 0, char c = ' ') {
this->i = i;
this->c = c;
}
int getI() { return i; }
char getC() { return c; }
friend ostream& operator << (ostream&, A&);
};
class B : public A {
double d;
public:
B(int i = 0, char c = ' ', double d = 0.0) : A(i, c), d(d) {}
friend ostream& operator << (ostream&, B&);
};
ostream& operator << (ostream& out, A& a) {
out << "\nInteger: " << a.i << "\nCharacter: " << a.c << endl;
return out;
}
ostream& operator << (ostream& out, B& b) {
out << "\nInteger: " << b.getI() << "\nCharacter: " << b.getC() << "\nDouble: " << b.d << endl;
return out;
}
int main() {
A* a = new A (10, 'x');
B* b = new B(20, 'y', 5.23);
A* array[] = { a, b };
cout << *(array[0]);
cout << "\n______________________________\n";
cout << *(array[1]);
delete a;
delete b;
cin.get();
return 0;
}
How can I make cout << *(array[1]); call the overloaded stream insertion operator that takes an object of B as one of it's arguments?
You can't make it call the overloaded operator, since overloading is resolved at compile time.
To do resolution at runtime, i.e. use dynamic dispatch, you need to move the code that does the printing to a virtual member function.
Then call that from the operator (you only need one, for the base class).
class A
{
public:
// ...
// Override this in B
virtual void print(std::ostream& o) const
{
o << "\nInteger: " << i << "\nCharacter: " << c << endl;
}
// ...
};
ostream& operator << (std::ostream& out, const A& a) {
a.print(out);
return out;
}
Related
I was trying to learn operator overloading in C++ PL. I made an exercise shown below. What I want to do is overload << operator for each derived class and use it on my main. But whenever I do it, its only working for Base class. What is the problem here?
Class Employee:
class Employee {
public:
string name;
int id;
int exp_level;
double salary;
Employee() {
this->name = "";
this->id = 0;
this->exp_level = 0;
this->salary = 0.0;
}
~Employee() {
//WTF
}
virtual void calculateSalary() {
//CODE
}
virtual void registerX() {
//CODE
}
friend ostream& operator<<(ostream& os, const Employee& e) {
os << e.name << " " << e.exp_level << " " << e.id << " " << e.salary << endl;
return os;
}
};
Class Technical:
class Technical : public Employee {
public:
string profession;
Technical() {
this->profession = "";
}
~Technical() {
}
virtual void calculateSalary() {
//CODE
}
virtual void registerX() {
//CODE
}
friend ostream& operator<<(ostream& os, const Technical& e) {
os << e.name << " " << e.exp_level << " " << e.id << " " << e.salary << "Technical" << endl;
return os;
}
};
Class Engineer:
class Engineer : public Employee {
public:
Engineer() {
}
~Engineer() {
}
virtual void calculateSalary() {
//CODE
}
virtual void registerX() {
//CODE
}
friend ostream& operator<<(ostream& os, const Engineer& e) {
os << e.name << " " << e.exp_level << " " << e.id << " " << e.salary << "Engineer" << endl;
return os;
}
};
Main Method:
int main()
{
Employee* e = new Employee();
Employee* t = new Technical();
Employee* ee = new Engineer();
cout << *e << endl;
cout << *t << endl;
cout << *ee << endl;
}
Output:
0 0 0
0 0 0
0 0 0
C++ chooses the best overload based on the static type's of the function arguments, and because the type is Employee in this case, the Employee's operator<< gets called.
If you want it to call the correct version when you have a static type pointer / reference to it that doesn't match it's dynamic type you'll have to use a virtual function or use dynamic_casts / typeid to check for the concrete runtime type (virtual functions are the cleanest approach imho)
Example: godbolt
class Employee {
public:
virtual ~Employee() = default;
friend std::ostream& operator<<(std::ostream& os, const Employee& e) {
return e.put(os);
}
protected:
virtual std::ostream& put(std::ostream& os) const {
os << "Employee!";
return os;
}
};
class Technical : public Employee {
protected:
std::ostream& put(std::ostream& os) const override {
os << "Technical Employee!";
return os;
}
};
class Engineer : public Employee {
protected:
std::ostream& put(std::ostream& os) const override {
os << "Engineer Employee!";
return os;
}
};
int main() {
Employee* e = new Employee();
Employee* t = new Technical();
Employee* ee = new Engineer();
std::cout << *e << std::endl;
std::cout << *t << std::endl;
std::cout << *ee << std::endl;
delete ee;
delete t;
delete e;
}
would result in:
Employee!
Technical Employee!
Engineer Employee!
Also keep in mind that once you have at least 1 virtual function in a class then the destructor should almost definitely be also virtual.
e.g.:
Employee* e = new Technical();
delete e;
would only call ~Employee(), but not ~Technical(), if the destructor is not virtual.
So whenever you want to delete an object through a pointer to one of it's base-classes the destructor needs to be virtual, otherwise it's undefined behavior.
Due to these declarations
Employee* e = new Employee();
Employee* t = new Technical();
Employee* ee = new Engineer();
the static type of the expressions *e, *t, *ee is Employee &. So the operator
friend ostream& operator<<(ostream& os, const Employee& e)
is called for all three objects.
A simple way to make the friend operator << "virtual" is to define in each class a virtual function like for example
virtual std::ostream & out( std::ostream & ) const;
and define the (only) friend operator like
friend ostream& operator<<(ostream& os, const Employee& e)
{
return e.out( os );
}
The virtual function out need to be redefined in each derived class.
In C++ is there a way to use the insertion operator for a class method?
This operator<< overload is working:
class Complex {
public:
//Normal overload:
friend std::ostream& operator<<(std::ostream &out, const Complex &o) {
out << "test overload";
return out;
}
Complex() {};
~Complex() {};
};
I can do this:
int main()
{
Complex* o = new Complex();
std::cout << "This is test: " << *o << "." << std::endl; // => This is test: test overload.
}
I know about stream manipulators, like this:
std::ostream& welcome(std::ostream& out)
{
int data = 1;
out << "WELCOME " << data << "\r\n";
return out;
}
int main()
{
std::cout << "Hello " << welcome; // => "Hello WELCOME 1\r\n"
}
How can I put the welcome method into the Complex class and then how shall I call it from cout (please note that welcome method must access some class member variables)?
My trial:
class Complex {
public:
//Normal overload:
friend std::ostream& operator<<(std::ostream &out, const Complex &o) {
out << "test overload";
return out;
}
std::ostream& welcome(std::ostream& out) {
out << "WELCOME " << data << "\r\n";
return out;
}
Complex() { data = 1; };
~Complex() {};
private:
int data;
};
int main()
{
Complex* o = new Complex();
std::cout << "This is test2: " << o->welcome << std::endl; // compile error
}
One easy way to pick a different << overload is to use a different type.
#include <iostream>
class Complex {
public:
//Normal overload:
friend std::ostream& operator<<(std::ostream &out, const Complex &o) {
out << "test overload";
return out;
}
struct extra_info {
const Complex& parent;
extra_info(const Complex& p) : parent(p) {}
friend std::ostream& operator<<(std::ostream& out, const extra_info& ei){
int i = 1;
out << "extrainfo " << i;
return out;
}
};
extra_info extrainfo() {
return {*this};
}
Complex() {};
~Complex() {};
};
int main() {
Complex c;
std::cout << c << "\n";
std::cout << c.extrainfo();
}
Output:
test overload
extrainfo 1
I suppose in your real code you are using members. Hence the helper type must hold a reference to the Complex instance.
how to overload assignment operator to satisfy ob1=ob2=ob3 (ob1,ob2,ob3 are objects of same class) where we have no concern for (ob2 = ob3) which is similar to (ob2.operator=(ob3)) but we need a parameter of type class when we are assigning this result to ob1 which is similar to (ob1.operator=(ob2.operator=(ob3)) below is the code that gives me error
#include<bits/stdc++.h>
using namespace std;
class A
{
public:
int x;
int *ptr;
A()
{
}
A(int a, int *f)
{
x = a;
ptr = f;
}
void operator=(A&);
};
void A::operator=(A &ob)
{
this->x = ob.x;
*(this->ptr) = *(ob.ptr);
}
int main()
{
int *y = new int(3);
A ob1, ob2, ob3(5, y);
ob1 = ob2 = ob3;
cout << ob1.x << " " << *(ob1.ptr) << endl;
cout << ob2.x << " " << *(ob2.ptr) << endl;
cout << ob3.x << " " << *(ob3.ptr) << endl;
return 0;
}
Your asignement operator should return a reference to *this, and be defined as
A& operator=(const A&);
or, better, pass by value and use the copy-and-swap idiom
A& operator=(A);
For an excellent intro to operator overloading, see this.
class a{
int *var = new int;
public:
//constructor and destructor
a(int a):var(new int(5)){}
~a() {delete var;}
int get() const {return *var}
//overload of + oporator
a operator+(const a & rhs){return a(*var+rhs.get()
//overload of ++ operator
a a::operator++ (int)
}
a a::operator+ (const a & rhs) {
return a(*itsRadius + rhs.get());
}
a a::operator++ (int){
a temp(*this);
*itsRadius= *itsRadius+1;
return temp;}
}
now when i do like this:
a c(10),d,g;
g=c+d;
i get g = to some address instead of 15 .
why is that?
and when i fo c++ i get an error (in the distructor when he try to delete),why is that?
Here is a working example. You need also to read about the rule of three:
#include <iostream>
class Int
{
int *_value;
public:
Int(int value) : _value(new int(value))
{
}
~Int()
{
delete _value;
}
Int(Int const &rhs) : _value(new int(*rhs._value))
{
}
Int & operator=(Int const &rhs)
{
*_value = *rhs._value;
return *this;
}
Int operator+(Int &rhs) const
{
return Int(*rhs._value + *_value);
}
operator int() const
{
return *_value;
}
};
int main(void)
{
Int a(10),
b(32),
c(a + b);
std::cout << c << "\n";
a = c;
std::cout << a << "\n";
}
And also, it is a bad idea to use raw C pointers in C++. Read about the std::unique_ptr.
o.k. so i solve the problem , this is the working code :
class SimpleCircle {
int *itsRadius;
public:
SimpleCircle():itsRadius(new int(5)) { cout << "constructor initialized" << endl;}
SimpleCircle(int num) { itsRadius = new int(num); cout << "constructor" << endl;}
SimpleCircle(const SimpleCircle &rhs) : itsRadius(new int(*rhs.itsRadius)){ cout << "copy constructor" << endl; }
~SimpleCircle(){ delete itsRadius; cout << "destructor" << endl;}
//perfect
int get() const {return *itsRadius;}
void set(int num) { *itsRadius = num;}
//-------
//plus operator
SimpleCircle operator+(const SimpleCircle &);
//inc operator
SimpleCircle operator++();
SimpleCircle operator++(int);
//= operator
SimpleCircle & operator=(const SimpleCircle &);
};
SimpleCircle SimpleCircle::operator+ (const SimpleCircle & rhs) {
return SimpleCircle(*itsRadius + *rhs.itsRadius);
}
SimpleCircle SimpleCircle::operator++() {
int a = *itsRadius;
++a;
*itsRadius=a;
return *this;
}
SimpleCircle SimpleCircle::operator++ (int){
SimpleCircle temp(*this);
*itsRadius= *itsRadius+1;
return temp;
}
SimpleCircle & SimpleCircle::operator= (const SimpleCircle & rhs) {
if (this == &rhs)
return *this;
*itsRadius = *rhs.itsRadius;
return *this;
}
int main()
{
SimpleCircle a;
cout << a.get() << endl;
SimpleCircle b(15);
cout << b.get() << endl;
SimpleCircle c = a + b;
cout << "a: "<< a.get() << endl;
cout << "b: " << b.get() << endl;
cout << "c: " << c.get() << endl;
a++;
cout << "a: " << a.get() << endl;
++a;
cout << "a: " << a.get() << endl;
now the reason in the former code i had 2 problem (that was 1 becoase of the outher)
1 c was equal to some garbege instead of a number
2 the program break in the end destructor
the reason was i forgat o add a operator= , so it didn't know how to treat to :
c=a+b;
after i fixed it , all come together nicely
In the last two lines of below program, static_cast<void*> and dynamic_cast<void *> behave differently. From what I understand, The result of a dynamic_cast<void*> always resolves to the address of the complete object. So it uses RTTI in some way. Could anyone explain how compilers uses RTTI to differentiate between the two.
#include <iostream>
using namespace std;
class Top {
protected:
int x;
public:
Top(int n) { x = n; }
virtual ~Top() {}
friend ostream& operator<<(ostream& os, const Top& t) {
return os << t.x;
}
};
class Left : virtual public Top {
protected:
int y;
public:
Left(int m, int n) : Top(m) { y = n; }
};
class Right : virtual public Top {
protected:
int z;
public:
Right(int m, int n) : Top(m) { z = n; }
};
class Bottom : public Left, public Right {
int w;
public:
Bottom(int i, int j, int k, int m): Top(i), Left(0, j), Right(0, k) { w = m; }
friend ostream& operator<<(ostream& os, const Bottom& b) {
return os << b.x << ',' << b.y << ',' << b.z<< ',' << b.w;
}
};
int main() {
Bottom b(1, 2, 3, 4);
cout << sizeof b << endl;
cout << b << endl;
cout << static_cast<void*>(&b) << endl;
Top* p = static_cast<Top*>(&b);
cout << *p << endl;
cout << p << endl;
cout << static_cast<void*>(p) << endl;
cout << dynamic_cast<void*>(p) << endl;
return 0;
}
Possible output: https://ideone.com/WoX5DI
28
1,2,3,4
0xbfcce604
1
0xbfcce618
0xbfcce618
0xbfcce604
From 5.2.7 / 7:
If T is "pointer to cv void," then the result is a pointer to the most
derived object pointed to by v. Otherwise, a run-time check is applied
to see if the object pointed or referred to by v can be converted to
the type pointed or referred to by T.
So using dynamic_cast<void*>(o) you get a pointer to the first byte of the most "derived" object (if o is polymorphic).
The code the compiler generates for dynamic_cast<void *>(...) is something like:
static_cast<void*>(dynamic_cast<most_derived_type *>(...))
This property is often used for serialization.