By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,148 Members | 1,447 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,148 IT Pros & Developers. It's quick & easy.

Templates: Come solve this puzzle....

P: n/a
The purpose of this puzzle is not to test your knowledge and
understanding of templates. Rather, it is to help me understand
why template based containers of entities behave differently than
template based containers of pointers to entities, specifically with
respect to dynamic binding.

The following code snippet explains what I am talking about. I have
defined a container of a base type, and in that I store instances of
the
derived type. When I invoke a virtual function, it is the base version
that gets called, not the derived version. This problem does not exist
with containers that store pointers instead.

////////////////////////////////////////////////////////////////
#include <iostream.h>
#include <list.h>

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";
}

Jul 23 '05 #1
Share this Question
Share on Google+
2 Replies


P: n/a
kb***@kaxy.com wrote:
The purpose of this puzzle is not to test your knowledge and
understanding of templates. Rather, it is to help me understand
why template based containers of entities behave differently than
template based containers of pointers to entities, specifically with
respect to dynamic binding.
[...]


Search for "slicing" WRT classes and copying.

V
Jul 23 '05 #2

P: n/a
<kb***@kaxy.com> wrote in message
news:11**********************@z14g2000cwz.googlegr oups.com...
The purpose of this puzzle is not to test your knowledge and
understanding of templates. Rather, it is to help me understand
why template based containers of entities behave differently than
template based containers of pointers to entities, specifically with
respect to dynamic binding.

The following code snippet explains what I am talking about. I have
defined a container of a base type, and in that I store instances of
the
derived type. When I invoke a virtual function, it is the base version
that gets called, not the derived version. This problem does not exist
with containers that store pointers instead.


C++ !!! It slices, it dices!

Research 'slicing', and note that polymorphism in C++
requires the use of a pointer or reference to the base
class.

-Mike
Jul 23 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.