1

An acquaintance of mine has shared some sample code that exhibits somewhat strange behavior. Basically the sample code has a base class and a derived class, which overrides a virtual method. There are two sets of STL lists, each containing two lists (i.e. four STL lists in all).

Set-A

  1. List of instances of base class, containing derived instances
  2. List of instances of derived class, containing derived instances

Set-B

  1. List of pointers to base class, containing pointers to derived instances
  2. List of pointers to derived class, containing pointers to derived instances

In Set-A the overridden method is not executed in the case where we have a list of instances of base class, containing derived instances.

The sample code follows:

#include <iostream>
#include <list>

using namespace std;

//***********************************************************************
//
//***********************************************************************
class Base {

protected:
    int i;

public:
    //-----------------------------------------------------------------------
    //
    //-----------------------------------------------------------------------
    Base(int m)
    {

        i = m;
    }

    //-----------------------------------------------------------------------
    //
    //-----------------------------------------------------------------------
    int get_i()
    {

        return i;
    }

    //-----------------------------------------------------------------------
    //
    //-----------------------------------------------------------------------
    virtual int xyz()
    {

        return i;

    }
    // Returns the value of the base
    // class attribute
};



//***********************************************************************
//
//***********************************************************************
class Derived : public Base {

protected:
    int j;

public:
    //-----------------------------------------------------------------------
    //
    //-----------------------------------------------------------------------
    Derived(int m, int n) : Base(m)
    {
        j = n;
    }

    //-----------------------------------------------------------------------
    //
    //-----------------------------------------------------------------------
    int get_j()
    {
        return j;
    }

    //-----------------------------------------------------------------------
    //
    //-----------------------------------------------------------------------
    int xyz()
    {
        return j;

    }
    // Returns the value of the derived
    // class attribute
};


//***********************************************************************
//
//***********************************************************************
typedef list<Base> BaseList;
typedef list<Base>::iterator BaseIterator;
typedef list<Derived> DerivedList;
typedef list<Derived>::iterator DerivedIterator;
typedef list<Base*> BasePtrList;
typedef list<Base*>::iterator BasePtrIterator;
typedef list<Derived*> DerivedPtrList;
typedef list<Derived*>::iterator DerivedPtrIterator;


//-----------------------------------------------------------------------
//
//-----------------------------------------------------------------------
main()
{
    Derived* d[5];

    for (int k1 = 0; k1 < 5; k1++)

    {
        d[k1] = new Derived(k1, 2 * k1);

        // The base attribute ('i') has value 0 through 4
        // The derived attribute value ('j') is double that
    }

    // Instance collection declarations
    BaseList bcollection;

    BaseIterator biter, beol;

    DerivedList dcollection;

    DerivedIterator diter, deol;

    // Pointer collection declarations
    BasePtrList bpcollection;

    BasePtrIterator bpiter, bpeol;

    DerivedPtrList dpcollection;

    DerivedPtrIterator dpiter, dpeol;

    for (int k2 = 0; k2 < 5; k2++)
    {
        //Insert elements in base collection
        bcollection.insert(bcollection.begin(), *d[k2]);

        //Insert the SAME elements in the derived collection
        dcollection.insert(dcollection.begin(), *d[k2]);

        //Insert elements in base-ptr collection
        bpcollection.insert(bpcollection.begin(), d[k2]);

        //Insert the SAME elements in the derived-ptr collection
        dpcollection.insert(dpcollection.begin(), d[k2]);
    }

    cout << "** Instance-collection behavior **\n";

    // Iterate through the base collection and execute the
    // virtual method "xyz()" on each element
    cout << "Base collection:" << endl;

    beol = bcollection.end();

    for (biter = bcollection.begin(); biter != beol; biter++)
        cout << "  get_i()=" << (*biter).get_i() << ", xyz()="
             << (*biter).xyz() << endl;

    // Iterate through the derived collection and execute the
    // virtual method "xyz()" on each element.  Since we entered
    // the exact same elements in both lists, the EXPECTED output
    // is the same as before.
    //
    // Check out for yourself ;-(
    //
    cout << "Derived collection:" << endl;

    deol = dcollection.end();

    for (diter = dcollection.begin(); diter != deol; diter++)
        cout << "  get_i()=" << (*diter).get_i() << ", xyz()="
             << (*diter).xyz() << endl;

    cout << "The exact same elements were entered in both collections.\n"
         << "Is the output the same in both the cases?\n";

    cout << "\n\n** Pointer-collection behavior **\n";

    // Iterate through the base-pointer collection and execute the
    // virtual method "xyz()" on each element
    cout << "Base-pointer collection:" << endl;

    bpeol = bpcollection.end();

    for (bpiter = bpcollection.begin(); bpiter != bpeol; bpiter++)
        cout << "  get_i()=" << (*bpiter)->get_i() << ", xyz()="
             << (*bpiter)->xyz() << endl;

    // Iterate through the derived-pointer collection and execute the
    // virtual method "xyz()" on each element.  Since we entered
    // the exact same elements in both lists, the EXPECTED output
    // is the same as before.
    //
    // No surprises this time around :-(
    cout << "Derived-pointer collection:" << endl;

    dpeol = dpcollection.end();

    for (dpiter = dpcollection.begin(); dpiter != dpeol; dpiter++)

        cout << "  get_i()=" << (*dpiter)->get_i() << ", xyz()="
             << (*dpiter)->xyz() << endl;

    cout << "The exact same elements were entered in both collections.\n"
         << "Is the output the same in both the cases?\n";
}
Sandeep
  • 1,245
  • 1
  • 13
  • 33

0 Answers0