7

I have the following setup:

main.cpp:

int main() { vector <Tour> tourList; Tour* tour_ptr; for (unsigned int i = 0; i < tourList.size(); i++) { tour_ptr = &tourList[i]; tour_ptr->display(); } } 

Tour.h:

class Tour { public: virtual void display(); }; 

Tour.cpp:

void Tour::display() { cout << "Tour ID: " << getID() << "\n"; cout << "Description: " << getdescription() << "\n"; cout << "Tour Fee: $" << getfee() << "\n"; cout << "Total Bookings: " << getbookings() << "\n\n"; } 

GuidedTour.h:

class GuidedTour : public Tour { public: void display(); }; 

GuidedTour.cpp:

void GuidedTour::display() { Tour::display(); cout << "Max Tour Group Size: " << getMaxTourists() << "\n"; cout << "Tour Guide: " << getGuideName() << "\n"; cout << "Tour Date: " << getTourDate() << "\n\n"; } 

GuidedTour inherits from the Tour class, and I've specified the display() function as virtual in the base Tour class, but for some reason, the GuidedTour display() function never gets called, only the base function gets called every time. What am I doing wrong?

5
  • 2
    In your vector you should store Tour* not instances of Tour otherwise you cannot store GuidedTour instances in it. Commented Sep 17, 2013 at 5:04
  • You are suffering from slicing. Your GuidedTour is being sliced into a Tour when placed into the vector. Commented Sep 17, 2013 at 5:06
  • So I googled "object slicing" and apparently the solution is to make the base class pure virtual. That is not an option for me, because I need to be able to instantiate objects of the base Tour class. What other options do I have? Commented Sep 17, 2013 at 5:13
  • That is not the solution. The solution is not to downcast objects by value. Commented Sep 17, 2013 at 6:11
  • @user2742003: The vector<Tour> holds Tour objects. It can NOT hold GuidedTour objects so if you push one into the vector it slices off the Tour part and puts it in the vector. If you want to hold polymorphic objects in a vector you need to use pointers std::vector<Tour*> or preferably boost::ptr_vector<Tour> Commented Sep 17, 2013 at 8:37

3 Answers 3

11

Your code actually doesn't print anything as the std::vector would initially be empty. Other than that, your problem is caused by object slicing (I'm assuming that you are push_back()ing GuidedTours into the vector).

When object slicing takes place, you are storing only the Tour part of your GuidedTour object(s), and that's the reason why you are seeing the output of Tour::display().

To solve your problem, you need to store the objects polymorphically, by using (smart) pointers and dynamically-allocating your objects.

int main() { vector <std::unique_ptr<Tour>> tourList; for(...) { tourList.push_back(std::make_unique<GuidedTour>(/* constructor parameters */)); ... tourList.push_back(std::make_unique<Tour>(/* constructor parameters */)); } for (unsigned int i = 0; i < tourList.size(); i++) { tourList[i]->display(); } } 

Notice that I am using std::unique_ptr/std::make_unique and not raw newed pointers. Using them would greatly ease you of the problem of manually managing and deleteing your objects, which sometimes[understatement] are the cause of bugs and undefined behavior.

Note that some people might suggest you to use boost::ptr_vector or something similar. Listen to them, especially if they give you arguments on why they are better than the alternatives.

Sign up to request clarification or add additional context in comments.

Comments

2

Your problem has nothing to do with your classes, rather how you are creating the object. Each element in the tourList vector is a tour, and nothing at compile time or runtime is there to determine that they are GuidedTours. In effect, GuidedTour is never called, because I don't see a GuidedTour object in your main anywhere.

2 Comments

I actually removed the the Tour and GuidedTour objects that I push_back'ed into the vector from the examples above , to save on space and make it more readable.
Ah, well then, see Mark's answer. By pushing onto a queue of Tours you are stripping away the GuidedTour portion of the object.
-1

I am agree with "It'sPete". because you haven't used the GuidedTour class. It will work if you use the following method.

int main() { vector <GuidedTour> tourList; Tour* tour_ptr; for (unsigned int i = 0; i < tourList.size(); i++) { tour_ptr = &tourList[i]; tour_ptr->display(); } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.