Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

Peon

Question about virtual functions

This topic is 5542 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I was under the impression that if you declared a memeber function 'virtual' in a base class and called it from subsequenent derived classes, it would use the definition in the drived class. Indeed, this is the case. However, if you make an array of the base class and try and call the virtual function, it reverts to the definition in the base class. Is there anyway I could do something like this?
//two different classes derived from cGeneric

cObjectA A;
cObjectB B;

cGeneric List[2];
List[0] = &A;
List[1] = &B;

//now we call a virtual member function

List[0].Write();
List[1].Write();
In the above example, the Write() function would simply take whatever definition it has in cGeneric. *I* want it to take the one in the derived class. Is there any way to do this, or do I need to maintain two separate, specific lists, one for each object (or as many lists as different objects I have)? [edited by - Peon on October 8, 2003 4:29:27 PM]

Share this post


Link to post
Share on other sites
Advertisement
quote:
Original post by superdeveloper
also, just to confirm, should it not be? :

cGeneric * List[2];

... and ...

List[0]->Write();
List[1]->Write();


Perhaps, maybe I wrote it wrong I still get confused a bit when I work with pointers/addresses, etc.. The above code MAY have errors in it.

Share this post


Link to post
Share on other sites
Well, for one thing you''re getting mixed up with pointer syntax...

but assuming that you want List to be an array of simple cGeneric objects, that won''t work. In C++, polymorphism only works with pointers to base classes, not actual instances of them.

Share this post


Link to post
Share on other sites
quote:
Original post by twix
Well, for one thing you''re getting mixed up with pointer syntax...

but assuming that you want List to be an array of simple cGeneric objects, that won''t work. In C++, polymorphism only works with pointers to base classes, not actual instances of them.

Yes I know I''m still getting than hand of it and rely a little too much on the compiler to help me out. But anyway..

I suspected as much, so I guess instead of a nice big list of objects, I''ll have to make a separate list for each type?

Share this post


Link to post
Share on other sites
Use pointers in this case.... that will work properly. The problem is.. if you define a class like this:


class baseClass
{
public:
int x;
int y;
virtual void Set(int num) { x = num; };
};

class Derived1 : public baseClass
{
virtual void Set(int num) { y = num; };
};

class Derived2 : public baseClass
{
virtual void Set(int num) { x = y = num; };
};


Doing a sizeof(baseClass) or any of the derived classes will yield an 8 (size of 2 ints). When you do it the way your application does:

Derived1 d1;
Derived2 d2;
baseClass Array[2];

Array[0] = d1;
Array[1] = d2;

Array IS still a baseClass, you just copied the DATA (x and y in this case) into it, so any functions you call will belong to baseClass. Now, if you use pointers:

Derived1 d1;
Derived2 d2;
baseClass *Array[2];

Array[0] = &d1;
Array[1] = &d2;

Then it WILL call the proper virtual function, as it's setting it's physical address to that of a derived type, so it will use it's functions rather than just copy it's data. Hope this helps a little bit .

--- Edit ---
One last note...

must use Array[0]->Set() rather than Array[0].Set(), since it's a pointer.


[edited by - Ready4Dis on October 8, 2003 5:09:58 PM]

Share this post


Link to post
Share on other sites
This issue is discussed (thoroughly) in Scott Meyers'' Effective C++ (Item 39). The List.operator[] returns a pointer of type cGeneric, which is why that one gets called. To "fix" this, people often simply downcast the List[] to the desired derived cast (cast down the inheritance hierarchy). This works, BUT Meyers points out that this is bad practice as it leads to a code-maintenance nightmare. He then goes on to give examples of problems you might have and how to fix them. However, it seems the "correct" fix (avoiding downcasts) requires rearranging the inheritance or changing your lists.

But I don''t have a full grasp on this yet, so I''m not sure if there''s another way. The new casting features (I think added to C++ with RTTI may be a way to do it, but I haven''t read about it yet).

Search some for C++ downcast - might find something.
Here''s a couple that look good (though I''ve only skimmed them):
Casting Basics
CPP Home Tutorial

Tadd
- WarbleWare

Share this post


Link to post
Share on other sites
quote:
Original post by Peon
quote:
Original post by twix
Well, for one thing you''re getting mixed up with pointer syntax...

but assuming that you want List to be an array of simple cGeneric objects, that won''t work. In C++, polymorphism only works with pointers to base classes, not actual instances of them.

Yes I know I''m still getting than hand of it and rely a little too much on the compiler to help me out. But anyway..

I suspected as much, so I guess instead of a nice big list of objects, I''ll have to make a separate list for each type?





No, just use a list of pointers rather than a straight list, this way it points to the proper derived type, otherwise doing an = to another type simply copies over it''s data members, not it''s virtual function addresses. When using the pointer method, it points to the derived type, and when you call it''s functions, it uses the proper virtual function address (which is stored in what''s called a vtable, so when you point to the proper type, it uses it''s local vtable rather than the base classes vtable, and when you don''t use a pointer, it''s still the baseClass type just copies the data over and uses the baseClass vtable).

Share this post


Link to post
Share on other sites
Thanks for the idea reagrding the array of pointers; it did exactly what I needed.

What I worry about though is that I will run out of memory, since I'm not sure how to use delete (in this case). Let me give an example:


void Input()
{
case FIRE:
cProjectile* NewBullet = new cProjectile;
NewBullet->LoadParameters("generic.prj");
AddObject(NewBullet);

//just soem debugging

//cMessage<MessageType, int, int> BulletMsg;

//BulletMsg.SetMessage(GET_LIFE, 0, 0);

}

In this example, I have created an input handling routine in my engine. If the user presses a button (FIRE, in this case), a new cProjectile is created. This is then added to a database of all the objects. I can't delete this bullet right after, because otherwise I will lose the values of it, when I need to maninpulate it from within the database. If I don't call delete, I have a memory leak, which is equally undesirable.

Basically what I have (now) is an array of pointers to all my objects. In this case, how would I go about deleting objects that I no longer need?

Sorry in advance for the new questions; I'm trying to build a good database class that is not game-specific, that I can use for many of my future projects.


[edited by - Peon on October 8, 2003 8:11:08 PM]

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!