aed@netcom.COM (Andrew Davidson) (02/07/91)
Hello I found an interesting anomaly when trying to implement a way to change the Vtable of an object. I have a ChangeModel() function void ChangeModel(Bond &b) { noop x; new(&b) UsersBond(x); // turns bond in to UsersBond } The problem I found is that if the object being passed to the function is on the stack that the Vtable is only changed with in the scope of the ChangeModel() function. as soon as this function returns, the object uses its original vtable? But if the object being passed is on the heap the vtable is changed both in the ChangeModel() function scope and the scope of the calling function. Could this be a bug with turbo C++, or am I missing something? (hopefully my Sys Admn will install my AT&T compiler, but I have already been waiting for over 6 months). I first tried this program with g++ 1.37.0, but gnu would not compile. thanks Andy here is the out put id: 1 amount: 10 npv: 20 id: 1 amount: 10 npv: 30 id: 1 amount: 10 npv: 30 id: 2 amount: 20 npv: 40 id: 2 amount: 20 npv: 60 id: 2 amount: 20 npv: 40 here is the Source ------------------------- cut here --------------------------- /* * by A. E. Davidson * * ref * CHANGING OPERATIONS" page 17 * in Bjarne Stroustrup`s article "Sixteen ways to stack a cat, part 2" * in Vol 2 Number 10 nov/dec 1990 The C++ Report * * the purpose of this example is to show a way to * change a bond objects CalcNpv() member function */ #include <iostream.h> class noop {}; class Bond; void* operator new(size_t,void *p); void ChangeModel(Bond &b); /* * Tran is used as a base class */ class Tran { public: virtual ~Tran() {;} virtual void CalcNpv() = 0; virtual void Display() = 0; protected: int npv; int id; static int nextAvailTranId; Tran(noop x) {;} Tran() { id = nextAvailTranId++; npv = 0; } }; /* * application defined object * contains a default princing model * CalcNpv() */ class Bond : public Tran { public: Bond(int value = 0) : Tran() {amount = value; CalcNpv(); } Bond(noop x) /* make an unitialized bond */ : Tran(x) {;} ~Bond() {;} void Display() { cout << "id: " << id << " amount: " << amount << " npv: " << npv <<"\n"; } void CalcNpv() { npv = amount * 2; } protected: int amount; }; /* * bogus class provide * so that user can define * his own pricing formula * with in our application * frame work */ class UsersBond : public Bond { public: UsersBond(noop x): Bond(x){;} void CalcNpv() { npv = amount * 3; } }; int Tran::nextAvailTranId = 1; /* * changes a bond object into * a UsersBond object * note * the representation of the * objects is not changed * all that is changed are * the virtual functions */ void ChangeModel(Bond &b) { noop x; new(&b) UsersBond(x); // turns bond in to UsersBond /* * test to see if vtable is change with in * function scope */ b.CalcNpv(); b.Display(); } void* operator new(size_t,void *p){return p;} main() { Bond *b1 = new Bond(10); Bond b2(20); b1->CalcNpv(); // 10 * 2 */ b1->Display(); ChangeModel(*b1); // change the virtual member functions for b1 b1->CalcNpv(); // should be 10 * 3 b1->Display(); b2.CalcNpv(); // 20 * 2 b2.Display(); ChangeModel(b2); // change the virtual member functions for b2 b2.CalcNpv(); // should be 20 * 3 b2.Display(); } -- ----------------------------------------------------------------- "bede-bede-bede Thats all Folks" Porky Pig Andy Davidson Woodside CA. aed@netcom.COM -----------------------------------------------------------------