Another noob c++ programming question. I'll ask it without the code first, but if the answer isn't obvious, I'll add the code
I have two classes:
class item (with virtual function display())
class test (derived from item, and with its own version of display())
Then I instantiate a bunch of item objects and a test object and push them all onto a list (list<item> items;) This all works fine. test makes it into the list because it is derived from item.
The problem comes later when I iterate through the list (using "list <item>::iterator i";) When it gets to the test object, it calls item's display() rather than test's display(). The reason I did all of this inheritance and virtual function code was so that i could put test into the items list and have its own display() method called.
It's operating like it thinks test is an item; so it's not dynamically binding test's display() method. Am I doing something wrong? I've verified that the method declarations and definition headers are identical.
Thanks.
-gss
c++ virtual function problem
Re: c++ virtual function problem
OK, simplified my code into the following example app showing the problem.
This results in the output:
I expected the last line to read "Test: Test", just like the 2nd line did when b->display() was called directly. I thought that despite the list being a list of "Item"s, when the object referenced is a "test", test's display would be called, but obviously that isn't the case. Any easy way to adjust this to get what I want?
EDIT: I also just tried pulling the items off of the list and referencing them with Item *, trying to re-create the objects as they were before being pushed onto the list, but it still always used Item's display().
Code: Select all
#include <iostream>
#include <string>
#include <list>
using namespace std;
class Item
{
public:
Item() {}
virtual void set_name (string new_name) {
name = new_name;
}
virtual void display() {
cout << "Item: " << name.c_str() << "\n";
}
protected:
string name;
};
class Test: public Item
{
public:
Test() {}
void display() {
cout << "Test: " << name.c_str() << "\n";
}
};
int main (int argc, char **argv)
{
Item *a,*b;
list <Item> items;
list <Item>::iterator i;
a = new Item();
b = new Test();
a->set_name("Item");
b->set_name("Test");
items.push_back(*a);
items.push_back(*b);
cout << "Calling display methods directly\n";
a->display();
b->display();
cout << "\nCalling display methods through the list iterator\n";
for (i=items.begin(); i != items.end(); ++i) {
i->display();
}
}
Code: Select all
Calling display methods directly
Item: Item
Test: Test
Calling display methods through the list iterator
Item: Item
Item: Test
EDIT: I also just tried pulling the items off of the list and referencing them with Item *, trying to re-create the objects as they were before being pushed onto the list, but it still always used Item's display().
Re: c++ virtual function problem
Instead of a list of type list<Item>, have a list of type list<Item *>. Here is an explanation from the C++ FAQ.
Generally, objects that are part of an inheritance hierarchy should be passed by reference or by pointer, not by value, since only then do you get the (desired) dynamic binding (pass-by-value doesn't mix with inheritance, since larger derived class objects get sliced when passed by value as a base class object).
Re: c++ virtual function problem
Ahhh yes, of course. Made the change and it works as expected. Thanks so much!
- gss
- gss