Object Functions

Started by
4 comments, last by Sammy0037 18 years, 9 months ago
Hi all Simple question really, but Im sure there is no single answer... Lets say there are 30 total copies of 4-5 classes. 4-5 vehicle types for example. They all share a common base and use many duplicate functions for control. Each copy has its own position info variables etc etc etc. Im looking at whether or not to put these functions inside the classes... in a sense allowing them to control themselves. Or, control them all from a higher level and only keep the variables. And maybe a specialized function or two if they exist. They would certainly be much smaller without all the functions, which I would think can make a difference as more and more copies are added. But maybe it doesnt? 30 is a pretty small number really. And I do see benefits in self contained packages (such as when one type needs something that the others dont). But I dont like duplicating things when I dont have to either. Cheers :o)
Advertisement
Are you using polymorphism?
class IVehicle{public:    virtual void drive();    virtual void stop();    // etc ...};class CTank : public IVehicle{private:    int ammo;    // etc ...public:    // I already can drive and stop!    void shoot();};

I apologize if you are already doing this, and if you are, I am not completely sure what exactly the problem is.
Yes, but at the moment only for common variables that the derived classes share... and the contructor&destructor.

Think of 100 'Car' objects in an array... AllCars[]. Also, 'Car' inherits 'Vehicle'. Move() is in 'Vehicle'... therefore in 'Car' also. So in effect each instance of 'Car' in 'AllCars[]' has its own copy of Move(). Then... AllCars[] is inside a single instance of class 'Manage'. There might also be 'AllTrucks[]', 'AllBoats[]', etc in 'Manage' as well..

Should I put Move() in 'Manage'? Or in 'Car'? Having 100 (or 200 or 300)copies of the same function floating around... one in each instance of 'Car'... seems inefficient. Should I tell 'AllCars[99]' to call that instances "Move()" function? Or pass 'Car[99]' to the same function, but is located in 'Manage' instead?

If I have the syntax right... "Car[99].Move()" vs. "Move(*car[99])".

Havent set any virtual functions yet. But its on my list ;o)
There is one copy of the method - it is passed an invisible and hidden pointer to the class (the 'this' pointer).
Quote:Original post by Sammy0037
Having 100 (or 200 or 300)copies of the same function floating around... one in each instance of 'Car'... seems inefficient.


But you see... that doesn't *happen* with the *code*. There is only ever one copy of the code sitting around in memory. What happens, for non-polymorphic member functions, is that they are translated into ordinary functions where the this-pointer is passed as an additional parameter. Even for polymorphic functions, all that needs to be added to each object is a *pointer* to a particular structure called a "v-table" (v for virtual); one of these is basically generated per *class*, and it contains pointers to the versions of the functions that are appropriate for the exact class types being used.

Thus if Move() is polymorphic for example, then the compiler says "ok, Vehicles and their derived classes have some polymorphic behaviour, so I need to add vtables". Then, a single vtable is generated for the base Vehicle class (assuming it can be instantiated and is not purely an abstract base), and one for the Car class; each contains a pointer to a different (translated) version of Move (and also pointers to any other virtual functions in the class). Then each Vehicle instance contains a pointer to the Vehicle-class vtable, and similarly for Cars. And a call to Move() from some Car*, for example (assuming that it's a Car* being stored in a Vehicle* pointer; if the type is known at compile-time, the compiler will use that) is translated into, roughly, "look up the vtable from the this-object pointer, access the '.Move' member of that vtable struct, and invoke that function pointer". Which is quite a bit faster than it sounds.

And in the case of more complicated inheritance, it is still set up in such a way that at most one vtable lookup will be required - if something is derived indirectly from a grandparent, it gets put directly into the current vtable, for example. (Making all of this work correctly with multiple inheritance is a difficult part of writing the compiler, and IIRC is part of the explanation for the phenomenon where pointers to the same multiply-derived object might appear to have different addresses.)
Ah, I see. That does help a great deal. And it also means theres alot of cleanup for me in the near future. Thanks ;o)

This topic is closed to new replies.

Advertisement