Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

list of polymorphic objects

I have a particular scenario below. The code below should print 'say()' function of B and C class and print 'B says..' and 'C says...' but it doesn't .Any ideas.. I am learning polymorphism so also have commented few questions related to it on the lines of code below.

class A
{
public:
// A() {}
    virtual void say() { std::cout << "Said IT ! " << std::endl; }
    virtual ~A(); //why virtual destructor ?
};

void methodCall() // does it matters if the inherited class from A is in this method
{
    class B : public A{
    public:
        // virtual ~B(); //significance of virtual destructor in 'child' class
        virtual void say () { // does the overrided method also has to be have the keyword  'virtual'
            cout << "B Sayssss.... " << endl; 
        }
    };
    class C : public A {
    public:
        //virtual ~C();
        virtual void say () { cout << "C Says " << endl; }
    };

    list<A> listOfAs;
    list<A>::iterator it;

    # 1st scenario
    B bObj; 
    C cObj;
    A *aB = &bObj;
    A *aC = &cObj;

    # 2nd scenario
    //  A aA;
    //  B *Ba = &aA;
    //  C *Ca = &aA; // I am declaring the objects as in 1st scenario but how about 2nd   scenario, is this suppose to work too?

    listOfAs.insert(it,*aB);
    listOfAs.insert(it,*aC);

    for (it=listOfAs.begin(); it!=listOfAs.end(); it++)
    {
        cout <<  *it.say()  << endl;
    }
}

int main()
{
    methodCall();
    return 0;
}
like image 889
mu_sa Avatar asked Feb 11 '12 16:02

mu_sa


1 Answers

Your problem is called slicing and you should check this question: Learning C++: polymorphism and slicing

You should declare this list as a list of pointers to As:

list<A*> listOfAs;

and then insert these aB and aC pointers to it instead of creating copies of objects they are pointing to. The way you insert elements into list is wrong, you should rather use push_back function for inserting:

B bObj; 
C cObj;
A *aB = &bObj;
A *aC = &cObj;

listOfAs.push_back(aB);
listOfAs.push_back(aC);

Then your loop could look like this:

list<A*>::iterator it;
for (it = listOfAs.begin(); it != listOfAs.end(); it++)
{
    (*it)->say();
}

Output:

B Sayssss....
C Says

Hope this helps.

like image 124
LihO Avatar answered Oct 15 '22 20:10

LihO