1

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?

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
Achintha Gunasekara
  • 1,165
  • 1
  • 15
  • 29
  • 1
    [this](http://stackoverflow.com/q/4571611/812912) may help – Ivaylo Strandjev Oct 15 '13 at 08:54
  • 2
    A virtual `read(std::stream&)` and `write(std::ostream&)` invoked from your friended base-class operators will eliminate the need for overrides of the operators in derived classes. The derivations override `read` and `write` (and can even invoke the base class directly as part of its derived functionality if needed). – WhozCraig Oct 15 '13 at 08:54
  • Can you please explain this bit more? sorry, i'm very new to C++ – Achintha Gunasekara Oct 15 '13 at 09:01
  • @Archie Any [good C++ book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) will explain this and much more. – Angew is no longer proud of SO Oct 15 '13 at 09:03
  • 1
    @Archie [follow the link in Ivaylo's comment above](http://stackoverflow.com/q/4571611/812912). Loki's response in that question is about as good a summary as you're going to see in the limited space of a SO answer. – WhozCraig Oct 15 '13 at 09:09
  • "I want to overload these operators differently on the subclass to do something else." ― no you don't. You want to override. The difference is important and you will do yourself a lot of favor by learning and internalizing it. – n. m. could be an AI Oct 15 '13 at 09:11

2 Answers2

3

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 :-)

Tristan Brindle
  • 16,281
  • 4
  • 39
  • 82
0

If i understood right, you have pointers in your vector. So you should use key word virtual. And read about virtual methods in C++.

Sukhanov Niсkolay
  • 1,298
  • 1
  • 12
  • 26