tour and guided tour. Guided tour extends the tour class. I'm overloading << and >> operators in the tour class.
My tour class looks like
#include <iostream>
#include <vector>
#include "Customer.h"
using namespace std;
class Tour {
protected:
string id;
string description;
double fee;
vector<string> customerList;
public:
Tour();
Tour(string idVal, string descriptionVal, double feeVal);
string getId();
string getDescription();
double getFee();
double getTotalForTour();
virtual void addCustomer(string cust);
vector<string> getCustomers();
virtual void display();
friend ostream& operator<< (ostream &out, Tour &cust);
friend istream& operator>> (istream &in, Tour &cust);
};
then my guided tour looks like this,
#include <iostream>
#include "Tour.h"
#include "SimpleDate.h"
using namespace std;
class GuidedTour : public Tour {
private:
SimpleDate* date;
string guideName;
int maxNumTourists;
public:
GuidedTour();
GuidedTour(string idVal, string descriptionVal, double feeVal, SimpleDate* dateVal, string guideNameVal, int maxNumTouristsVal);
virtual void addCustomer(string cust);
SimpleDate* getDate();
void display();
friend ostream& operator<< (ostream &out, GuidedTour &cust);
friend istream& operator>> (istream &in, GuidedTour &cust);
};
I want to overload these operators differently on the subclass to do something else.
I have a Vector that contains tours and guided tours.
When i loop through the vector and do following,
for (unsigned int i = 0; i < tourListVector.size(); i++) {
cout << *tourListVector[i];
}
It always does what's specified in tour regardless even if the object is a guided tour.
Can you please help?
You're almost doing the right thing, but not quite. Let's take the output case first -- the input case works just the same.
First, you should declare a
virtual void write(std::ostream&) const;
member function in your base class. The implementation might be something like:
void Tour::write(std::ostream& os) const
{
os << "ID: " << id << std::endl;
os << "Description: " << description << std::endl;
// etc
}
which I assume is the sort of code you have currently in your operator<<(ostream&, Tour&). Then you need to overload this in your derived class -- perhaps with something like
void GuidedTour::write(std::ostream& os) const
{
Tour::write(os); // Write out base Tour info first
os << "Guide Name: " << guideName << std::endl;
// etc
}
After that, you can declare a free (i.e. non-member) operator<< overload for Tours, which calls your write() member function, like
std::ostream& operator<<(std::ostream& os, const Tour& tour)
{
tour.write(os);
return os;
}
for example.
Explanation: Forget the fact that your current operator<< is a friend; it has no bearing in this case. Instead, imagine you have two overloaded non-member functions called
void do_something(Tour& t); // (a)
void do_something(GuidedTour& gt); // (b)
Since your tourListVector contains (I assume) Tour* pointers, if you were to loop through the vector and call do_something() on each element, the compiler would only be able to match function (a) above. That's because it has no way of knowing that some of the Tour* pointers might, for a given run of your programme, actually point to GuidedTour instances. In order to do run-time dispatching like this, you need to use virtual functions.
Aside: (I know this is example code, but if you're new to C++ then it's worth pointing out just in case you weren't aware :-) )
Because you're using Tour* pointers, you should define a virtual destructor for your base class. If you don't, the compiler won't know that it might need to destruct all the members of the GuidedTour class when you call delete on a Tour*. In fact, it's generally good practice to make your destructor virtual if your class includes any other virtual functions, just to save potential problems later.
Also, please don't put using namespace std; in a header file :-)
If i understood right, you have pointers in your vector. So you should use key word virtual. And read about virtual methods in C++.
Related
I'm trying to understand how to properly overload the "<<" operator so that I can use
std::cout << my_object;
to print useful debug messages. In particular, I need to have an implementation of << for each of my subclasses, so I'm declaring << to be virtual in the superclass.
Right now I'm stuck with the following piece of code
#include <iostream>
using namespace std;
class Shape {
public:
virtual ~Shape() { };
virtual ostream& operator<<(std::ostream &strm) = 0;
};
class Square : public Shape {
int size;
public:
Square() { size = 10; }
~Square() { }
ostream& operator<<(std::ostream &strm) {
return strm << "a square with size " << size;
}
};
int main() {
Square *my_square = new Square();
cout << "my_square is " << my_square << "\n";
}
which (I think) should be working, but doesn't. What I get when using "<<" is that the pointer value of my_square gets printed, rather than the result of the overloaded << .
$ ./a.out
my_square is 0xcacc20
What am I missing here?
operator<< can't be a member function. This is because of the order of the arguments. The stream has to come first.
When calling an overloaded operator, such as:
os << object;
the compiler will attempt to look up both
os.operator<<(object);
and
operator<<(os, object);
(The rules for this can be rather complex, I won't attempt to describe them here.)
Because the stream always comes on the left, your member function will never be found, since it would have to be called as:
object.operator<<(os);
You need to write a free function like:
ostream& operator<<(std::ostream &strm, Square const& square) {
return strm << "a square with size " << square.size();
}
(where Square::size() returns the size member).
Then you need to remember to dereference your pointer too:
std::cout << *my_square << '\n';
Although I see no reason to be dynamically allocating my_square in this example anyway. Just stick it on the stack as a local variable.
If the aim here is ultimately to be able to print any Shape&, and have the printed output follow the "real" type, you would need to create:
virtual std::ostream& print(std::ostream&) const = 0;
in the Shape base class, and override it in each derived class, then have a free function:
std::ostream& operator<<(std::ostream& os, Shape const& shape)
{
return shape.print(os);
}
It is often advised to make all binary operators on your type non-member functions, so that both arguments are treated equally, and the operation remains commutative. See Scott Meyers, Effective C++ (3rd Edition), Item 24, (or find a summary online).
As noted by others, the problem is that operator << can't be member function (because of the order of arguments). The canonical way to do this is to have operator <<(const Shape&) call a virtual function in Shape
class Shape {
friend ostream& operator<<(std::ostream& str, const Shape& shape);
virtual void do_print(ostream& str) = 0;
public:
virtual ~Shape() { };
};
ostream& operator<<(std::ostream& str, const Shape& shape) {
shape.do_print(str);
return str;
}
Note that it is legal to have do_print be private, even though it is going to be (must be) overridden by derived classes. You could make it protected though if you like.
What am I missing here?
You have created operator which will get you class as a first argument and stream as the second.
my_square << std::cout;
I'd create free function and to make it dynamic I'd call some virtual method in it
Does std::basic_ostream have an overload of operator << that accepts a std::basic_string object? I'm reading cppreference and there doesn't seem to be one listed.
Imagine you create your own class called Car which contains licence plates number, model/power of the engine, and bunch of other information. Now, imagine you want to provide nice way to print your car information into the file, or into the screen.
If you want to use basic_ostream overload, you have no luck, since there is no overload for your class defined. You may provide print_into_ostream method, or some other clever trick, but you've just realized that std::string also doesn't have the appropriate overload, and you still can do cout << myStr;. After a quick search, you find a solution that is applied into the std::string, and you can use it in your class like this:
class Car
{
std::string licence_plate, engine;
public:
// ... other here ...
friend ostream& operator<<(ostream& os, const Car& c);
};
ostream& operator<<(ostream& os, const Car& c)
{
os << c.licence_plate << "-" << c.engine;
return os;
}
And now you can use
cout << myCarObject << endl;
as with any built-in type.
std::string uses the same approach, and you can find documentation here.
There are non-member operators defined in the std namespace. See cppreference.
If you want to print an object of your class A, you overload << operator like this:
ostream & operator << (ostream & os, A &a)
{
os << a.data_member;
}
In the same fashion in the std namespace there is an overloaded operator that prints object of class string.
Specifically, I would like to be able to use the ostream operator << in two derived classes from a base class.
The program I am creating is supposed to print out product details for various "products" in a "virtual store". Among the products are two different kinds of books. Each of these books is supposed to hold their own:
ID number
Author
NumberOfPages
Year
In addition, type ChildrensBook needs to hold a minimum age, and TextBook needs to hold a grade.
I defined class Book and derived from it classes ChildrensBook and TextBook. My question is about using the ostream operator << to print out the information.
Can I define a generic << function in the Book class, which will print out all of the information common to both derived classes, and then refer to it in the redefinition of << in the derived classes?
For example,
//The parent class
ostream& operator<<(ostream& bookOutput, const Book& printBook) {
return bookOutput << printBook.ID << "Name " << printBook.name << "year:" << printBook.year";
}
And then in the derived class somehow:
//The derived classes
ostream& operator<<(ostream& TextBookOutput, const TextBook& printTextBook) {
return TextBookOutput << "TextBook: "
<< "[Here is where I want to print out all the details of the book that are members of the base class]" << "Grade:" << printTextBook.grade;
}
So I guess my question can be summed up as: Can I call the parent operator from within the child operator, and if so, what syntax do I use?
Another idea that occurred to me is to write a function for the child that uses the parent print operator, and then call that function from within the child's print operator. That would mean that I wasn't trying to call an operator while redefining it, but still calls for using the parent operator and separately redefining the child operator.
Sure.
You have an operator for Books, so use it. You can invoke it by giving it a reference to a book, and you can use the power of polymorphism to obtain a reference-to-base.
ostream& operator<<(ostream& TextBookOutput, const TextBook& printTextBook) {
return TextBookOutput << "TextBook: " << static_cast<const Book&>(printTextBook) << "Grade:" << printTextBook.grade;
}
return TextBookOutput << static_cast<Book const &>(printTextBook) << ...
As others pointed out, you should use downcasting to achieve what you are asking for. But I think you should consider a different approach as well: What you are doing right now is mixing static and dynamic polymorphism, this often isn't a good idea (which usually only manifests itself later on).
Here is the problem, consider what you've got already:
class Book { ... };
class TextBook : public Book { ... };
ostream& operator<<(ostream& os, const Book& book) {
return os << "Book: " << book.name << "\n";
}
ostream& operator<<(ostream& os, const TextBook& book) {
return os << "TextBook: " << book.name << "\n";
}
Everything will go as expected if you use it like this:
Book book;
TextBook textBook;
cout << book << "\n"; // prints out: Book: XYZ
cout << textBook << "\n"; // prints out: TextBook: XYZ
That is because the compiler will correctly determine the type of the book during compilation time (statically).
Now consider this other case:
Book * textBook = new TextBook();
cout << *textBook << "\n"; // prints out: Book: XYZ !
This is because the compiler can't know what higher type it is, it can be Book, TextBook or ChildrensBook. This can only be determined during runtime (dynamically) using virtual functions etc.
So in case you consider utilizing dynamic polymorphism I would prefer this approach:
class Book {
public:
virtual ostream& print(ostream& os) const { return os << "Book: XYZ"; }
// Don't forget virtual destructor.
virtual ~Book() {}
};
class TextBook : public Book {
public:
virtual ostream& print(ostream& os) const
{
// Here, you can also call the "print" method of the parent class
// like this: os << Book::print(os);
// or just invent your own like this:
return os << "TextBook: XYZ";
}
};
ostream& operator<<(ostream& os, const Book& book) {
// Will correctly decide during runtime whether
// to use Book::print or TextBook::print.
return book.print(os);
}
I want to make a class based on "ostream" that does some auto-formatting to generate comma- or tab-separated-value files. My idea was to override "operator<<" to have it insert a separator before each value (except at the beginning and end of a line), and also to quote strings before writing them. Within the overriding "operator<<" method, I wanted to call the method of the base class, but I can't get it to work right.
Here's an example (compiles with g++ 4.3.3):
#include <iostream>
#include <ostream>
#include <string>
using namespace std;
class MyStream: public ostream
{
public:
MyStream(ostream& out): ostream(out.rdbuf()) {}
template <typename T> MyStream& operator<<(T value)
{
ostream::operator<<('+');
ostream::operator<<(value);
ostream::operator<<('+');
return *this;
}
};
template<> MyStream& MyStream::operator<< <string>(string value)
{
ostream::operator<<('*');
ostream::write(value.c_str(), value.size()); // ostream::operator<<(value);
ostream::operator<<('*');
return *this;
}
int main()
{
MyStream mystr(cout);
mystr << 10;
cout << endl;
mystr << "foo";
cout << endl;
mystr << string("test");
cout << endl;
return 0;
}
The two "operator<<" methods (template and specialization) are there to handle strings differently than everything else. But:
The characters ('+'/'*') are printed as numbers and not characters.
The C-String "foo" prints as a memory address (I think).
If the "write" line is exchanged with the commented part, the compiler complains that there's "no matching function for call to 'MyStream::operator<<(std::string&)'", even though I thought I was explicitly calling the base class method.
What am I doing wrong? Any help greatly appreciated.
The operator<< overloads that prints strings and characters are free functions. But as you force calling member functions, you will force them to convert to one candidate of the member functions declared in ostream. For '*', it will probably use the int overload, and for "foo", it will probably use the const void* overload.
I would not inherit ostream, but instead store the ostream as a reference member, and then delegate from your operator<< to it. I would also not make operator<< a member, but rather a free function template, and not specialize but overload the operator<< for both std::string and char const*.
Something like the following might work:
include
#include <ostream>
#include <string>
using namespace std;
class MyStream: public ostream
{
public:
MyStream(ostream& out): ostream(out.rdbuf()) {}
template <typename T> MyStream& operator<<(const T& value)
{
(ostream&)*this << '+' << value << '+';
return *this;
}
MyStream& operator<< (const string& value)
{
(ostream&)*this << '*' << value << '*';
return *this;
}
MyStream& operator<< (const char* cstr)
{
(ostream&)*this << '(' << cstr << ')';
return *this;
}
};
Hey. Is it possible to overload operator<< for primitive types? Fx lets say that I want to write a std::endl each time want to write a int. Can I overload operator<< for int, so that it automatic puts a std::endl to the output? I have tried with this,
std::ostream& operator<<(std::ostream& strm, int & i)
{
strm << i << std::endl;
return strm;
}
but it doesn't work. I cant recall the compiler error message, but I think that I'm getting operator overloading all wrong any ways.
I try to call the above overloaded operator<< in this way,
int main()
{
int i = 2;
std::out<<"Here is an int " << i;
return 0;
}
But it doesn't work at all. Maybe I can't overload POD types?
As zabzonk said, the standard library provides an (ostream&, int) overload so you can't define another.
To simulate what you were doing (though it is completely pointless in its present form :) :
class EndlinedInteger {
public:
EndlinedInteger(int i) : i(i) { }
friend ostream& operator<<(ostream&, EndlinedInteger const&);
private:
int i;
};
ostream& operator<<(ostream& out, EndlinedInteger const& ei) {
out << ei.i << endl;
return out;
}
int main()
{
EndlinedInteger i = 2;
std::cout<<"Here is an int " << i;
}
Remember that here you use << operator not only on int but also on ostream. You could derive from ostream and implement it in your own derived class, but I would suggest to make a simple macro like
#define EL(i) (i)<<std::endl
Alternatively you could make boxed int class and override the << for standard ostream and boxed int (like in answer by Iraimbilanja) class. Sounds like huge overkill but could work.
Your problem is that there is already an overload for operator << (ostream &, int), the one supplied by the C++ standard library. If you remove the overload definition and use:
#include <iostream>
int main()
{
int i = 2;
std::out<<"Here is an int " << i;
return 0;
}
things work as expected.
And BTW, compiler error messages are kind of important, so it's a good idea to remember them and quote them in posts when asking questions.
edit - std::out above should of couse be std::cout