Overloading << operator with polymorphism - c++

I have read some similar questions and answers at SO, but don't really understand the answers there. My apologies, if this is a duplicate.
Have a base class like this.
class CParam
{
public:
virtual void PrintData(ostream &OutStream) = 0;
};
Now I inherit from this:
class CUInt32:public CParam
{
public:
void PrintData(ostream &OutStream);
}
void CUInt32::PrintData(ostream &OutStream)
{
// Write some data to OutStream Here
}
I overload operator << for CUInt32 class
inline ostream &operator<<(ostream &OutStream, CUInt32 &UInt32Obj)
{
UInt32Obj.PrintData(OutStream);
return (OutStream);
}
In int main() function I do the following:
int main()
{
CParam *cp = new CUInt32(ANALOG);
cout << *cp;// Error
return 0;
}
I get an error saying
error: no match for 'operator<<' in 'std::cout << *cp'|
My questions are
Is it possible to use polymorphic base class pointers with cout?
If yes, how we could do this?
Thanks for your time!

The operator is not defined for the base class.
Simply change this:
inline ostream &operator<<(ostream &OutStream, CUInt32 &UInt32Obj)
{
UInt32Obj.PrintData(OutStream);
return (OutStream);
}
to this:
inline ostream &operator<<(ostream &OutStream, CParam& cParam)
{
cParam.PrintData(OutStream);
return (OutStream);
}
Basically, defining the PrintData in the base class as virtual/abstract ensures it will be available for all subclasses and the correct function will be called.

Along with the obvious point (operator<< should take a reference to a const base) you also want to change your definition of PrintData to make it a constmember function, so it can be invoked on a const object. The resulting code ends up something like this:
struct CParam {
virtual void PrintData(ostream &OutStream) const = 0;
};
struct CUInt32 : CParam {
void PrintData(ostream &OutStream) const {}
};
ostream &operator<<(ostream &OutStream, CParam const &UInt32Obj) {
UInt32Obj.PrintData(OutStream);
return (OutStream);
}

Since overloading code uses PrintData, you could define the function at base class level itself. Since compiler couldn't find any overloading at base class level, it throws exception.

Related

C++ - ostream (<<) overloading

I was wondering if there is any way to overload the << operator for a class without declaring it as a friend function. My professor said this is the only way to do it, but I wanted to know if there is another way that he was unaware of.
There is no need to make the operator<< function a friend of the class as long as everything you want to be output is accessible through the public interface of the class.
You need to declare it is as friend function if and only if you need access to it's private members.
You can always do this without using friend function if:
1) No private member access is required.
2) You provide a mechanism to access your private member otherwise. e.g.
class foo
{
int myValue;
public:
int getValue()
{
return myValue;
}
}
Yes, you can
std::ostream& operator<<(std::ostream &stream, WHATEVER_TYPE var) {
std::string str = somehowstringify(var);
return stream << str;
}
Note however that by virtue of it being a non-member non-friend function it can of course only access the public interface of std::ostream, this usually isn't a problem.
Yes, one way to do it is like this:
class Node
{
public:
// other parts of the class here
std::ostream& put(std::ostream& out) const { return out << n; };
private:
int n;
};
std::ostream& operator<<(std::ostream& out, const Node& node) {
return node.put(out);
}
As R Sahu has pointed out, the requirement is that the operator should be able to access everything it has to display.
Here are a few possible options
1.Adding the overloaded function as a friend function
2.Making all the required data members of the class accessible for the function using either public accessor methods or public data members
class MyClass {
private:
int a;
int b;
int c;
public:
MyClass(int x,int y,int z):a(x),b(y),c(z) {};
MyClass():a(0),b(0),c(0) {};
int geta() { return a; }
int getb() { return b; }
int getc() { return c; }
};
std::ostream& operator<<(std::ostream &ostr,MyClass &myclass) {
ostr << myclass.geta()<<" - " << myclass.getb() << " - " << myclass.getc() ;
return ostr;
}
int main (int argc, char const* argv[])
{
MyClass A(4,5,6);
cout << A <<endl;
return 0;
}
3.Add a public helper function , say output with the signature std::ostream& output(std::ostream& str) and use it later in the operator function.

Overloading << error

I am kind of newbie to programming migrated from legacy turbo c++ to VS C++2012,I have a tough time catching up and i wanted to emulate the string library for TC. But i cant make the insertion operator work in this code....Please help Out. Could you tell the mistake i made in this code. And also why are we returning the object via reference for overloading.
#include<iostream>
#include<string>
namespace String
{
class string
{
char word[100];
int size;
public:
string()
{
size=0;
}
string(int sz)
{
size=sz;
}
string(char *Word)
{
strcpy(word,Word);
size=sizeof(*Word);
}
~string()
{
}
string &operator+(string Add)
{
strcat(word,Add.word);
return *this;
}
string &operator=(char *Word)
{
strcpy(word,Word);
return *this;
}
/*
ostream &operator<<(ostream &sout,string Show)
{
sout<<Show.word;
return sout;
}
*/
void Show()
{
std::cout<<word;
}
};
}
void main()
{
String::string A="ABCDEF";
String::string B="GHIJK";
String::string C;
C=A+B;
C.Show();
std::cin.ignore(2);
//std::cout<<C;
}
You should declare operator<< as a non-member function, because ostream will be taken as the 1st argument for operator<<, a user define type's member function can't satisfy it.
namespace String
{
class string
{
...
public:
ostream& put(ostream &sout) { sout << word; return sout; }
};
ostream& operator<<(ostream& sout, string Show) { return Show.put(sout); }
}
The output operator << has to be overloaded in the namespace, not the class itself if you want to be able to use it like so:
cout << my_class_object;
So, in the declaration of your class (string.h) add this line:
ostream &operator<<(ostream & sout,const string & Show);
And then in the definition file (string.cpp) in your namespace, not the class itself, ad this function:
ostream & operator<<( ostream & out, const bigint & data )
{
// the printing implementation
}

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

How do I make a class in C++ so that it acts like a native int class

I am learning C++, and learned that int-types are just premade classes. So I thought maybe i should try to create one.
What I want to do basically is a
normal class of int
int x;
x=7;
cout << x;
// Output is 7 on screen.
so similarly...
abc x;
x=7;
cout << x;
What would I put in
class abc{
\\ HERE!!!!!!
};
so I could do this
class SomeClass {
public:
int x;
SomeClass(int x) {
this->x = x;
}
};
int main(int argc, char *argv[]) {
SomeClass s = 5;
cout << s.x << "\n"; // 5
s = 17;
cout << s.x << "\n"; // 17
return 0;
}
But as you can see I have to use s.x to print the value - I just want to use 's'.
I am doing it as an experiment, I don't want to hear about how this method is good or bad, pointless or revolutionary, or can 't be done. I remember once I did it. But only by copying and pasting code that I didn't fully understand, and have even forgotten about.
and learned that int, types, are just premade classes
This is completely false. Still, you have complete control on how your class will behave in expressions, since you can overload (almost) any operator. What you are missing here is the usual operator<< overload that is invoked when you do:
cout<<s;
You can create it like this:
std::ostream & operator<<(std::ostream & os, const SomeClass & Right)
{
Os<<Right.x;
return Os;
}
For more information, see the FAQ about operator overloading.
the << and >> are basically function names. you need to define them for your class. same with the +, -, * and all the other operators. here is how:
http://courses.cms.caltech.edu/cs11/material/cpp/donnie/cpp-ops.html
You need to overload operator<< for your class, like so:
class abc
{
public:
abc(int x) : m_X(x) {}
private:
int m_X;
friend std::ostream& operator<<(std::ostream& stream, const abc& obj);
};
std::ostream& operator<<(std::ostream& os, const abc& obj)
{
return os << obj.m_X;
}
You don't have to friend your operator<< overload unless you want to access protected/private members.
You must define in your class abc cast operator to int and assignment operator from int, like in this template class:
template <class T>
class TypeWrapper {
public:
TypeWrapper(const T& value) : value(value) {}
TypeWrapper() {}
operator T() const { return value; }
TypeWrapper& operator (const T& value) { this->value = value; return *this; }
private:
T value;
};
int main() {
TypeWrapper<int> x;
x = 7;
cout << x << endl;
}
You want to overload the output operator:
std::ostream& operator<< (std::ostream& out, SomeClass const& value) {
// format value appropriately
return out;
}

C++ distinguishing structurally identical classes

I have several types that share common behaviour and with same constructors and operators. Some look like this:
class NumberOfFingers
{
public:
void operator=(int t) { this->value = t; }
operator int() const { return this->value; }
private:
int value;
};
NumberOfToes is identical.
Each class has different behaviour, here is an example:
std::ostream& operator<<(std::ostream &s, const NumberOfFingers &fingers)
{
s << fingers << " fingers\n";
}
std::ostream& operator<<(std::ostream &s, const NumberOfFingers &toes)
{
s << toes << " toes\n";
}
How can I minimise the duplication in the class definitions, whilst keeping class types distinct? I don't want to have NumberOfFingers and NumberOfToes derive from a common base class because I lose the constructor and operators. I would guess a good answer would involve templates.
Yes, you are correct in that it would involve templates :)
enum {FINGERS, TOES...};
...
template<unsigned Type> //maybe template<enum Type> but I havent compiled this.
class NumberOfType
{
public:
void operator=(int t) { this->value = t; }
operator int() const { return this->value; }
private:
int value;
};
...
typedef NumberOfType<FINGERS> NumberOfFinger
typedef NumberOfType<TOES> NumberOfToes
... so on and so forth.