Using virtual functions [closed]

I am starting to use virtual functions, and i am programming a simple text game, my question is this, if i have a virtual function called spec_abil with in a Super class called rpg_class. If you allow the player to class what class they want to play, say a mage class, a archer class, and a warrior class, which all have their own spec_abil function. How do you write it so that the program knows which one to use depending on the chosen class.

closed as off topic by TetradMar 25 '12 at 17:16

Questions on Game Development Stack Exchange are expected to relate to game development within the scope defined by the community. Consider editing the question or leaving comments for improvement if you believe the question can be reworded to fit within the scope. Read more about reopening questions here. If this question can be reworded to fit the rules in the help center, please edit the question.

• It sounds like you're a beginner at C++. Nothing wrong with that, but I strongly advise you to get and read the Scott Meyers book Effective C++. With some languages a quick answer on stackoverflow is fine, but there are lots of subtleties with C++ that if you don't know about them can introduce hard to understand bugs. – U62 Mar 25 '12 at 10:16
• Although the context is related to game development, the connections stops there. You question is completely programming related, and I believe that it should have been asked on SO, not SEGD. Maybe a mod could move it? There's nothing bad about the question, though. – jcora Mar 25 '12 at 16:34
• Even still, this is a post about using virtual functions as they relate to games. I think it's very on topic, and should not have been closed. -1 – onedayitwillmake Mar 25 '12 at 19:13

It's automatic as long as you're calling the virtual method through a pointer or reference to your base class - that's the beauty of polymorphism! So to give a typical example using pointers, imagine you had these three classes:

class rpg_class
{
public:
virtual void special_ability() { cout << "Generic ability"; }
}

class mage : public rpg_class
{
public:
void special_ability() { std::cout << "Mage ability"; }
}

class warrior : public rpg_class
{
public:
void special_ability() { std::cout << "Warrior ability"; }
}


The following example would automatically work:

std::vector<rpg_class*> characters;
characters.push_back(new mage());
characters.push_back(new warrior());
characters[0]->special_ability();   // Prints "Mage ability"
characters[1]->special_ability();   // Prints "Warrior ability"


And it works because the vector is storing pointers to the base class (i.e. rpg_class* instead of simply rpg_class).

PS: You might also want to consider using a smart pointer such as std::unique_ptr if your compiler supports it instead of a regular pointer, as this will free you from having to delete your objects explicitally. All smart pointers are also made to work under polymorphism afaik.

• would you fill characters[1]->special_ability(//here); with the function parameters, say health or power – Tucker Morgan Mar 25 '12 at 2:24
• @TuckerMorgan That's a design choice, and not really related to your question about virtual functions. More specifically I don't really have enough information about your design to answer if it makes sense for that function to have those parameters or not. But yes you can add parameters to your virtual function, as long as you repeat those parameters in every subclass too. If you use different parameters in one of the subclass implementations, it will no longer be overriding the virtual function so you won't get the correct behavior. They must all match. – David Gouveia Mar 25 '12 at 2:29
• i was just wondering where you passed them from, for all of the sub class functions they will have the same parameters – Tucker Morgan Mar 25 '12 at 2:37

Declaring a method as virtual in a base class causes the compiler to introduce a hidden pointer into objects of this class (and its derived classes). This is the vfptr, the pointer to the vtable. This pointer and table can be absent in classes that do not declare any virtual methods. The vtable holds the addresses of the correct methods to call. There is one vtable per class. When an object is constructed, its vfptr is set to point to the appropriate vtable in order to make this all work. All virtual method calls are indirectly looked up in this vtable to provide the polymorphism. Therefore, determining which method to call takes place at run time, not compile time or link time.

You must be aware of how virtual methods work in order to use them safely. I recommend further reading, inclusing virtual destructors (very important).

Polymorphism can be exploited with or without pointers, using dynamically allocated objects or automatically cleaned up objects. References can be used instead of pointers:

class BaseClass {
public:
virtual void fn() {
printf("Base::fn()\n");
}
};

class Derived1 : public BaseClass {
public:
virtual void fn() {
printf("Derived1::fn()\n");
}
};

class Derived2 : public BaseClass {
public:
virtual void fn() {
printf("Derived2::fn()\n");
}
};

void useRef(BaseClass& b) {
b.fn();
}
void usePtr(BaseClass* pb) {
pb->fn();
}
void testVirtuals() {
Derived1 d1;
Derived2 d2;
useRef(d1);
useRef(d2);
usePtr(&d1);
usePtr(&d2);
Derived2* pd2Dynamic = new Derived2();
usePtr(pd2Dynamic);
delete pd2Dynamic;
}


Produces this output:

Derived1::fn()
Derived2::fn()
Derived1::fn()
Derived2::fn()
Derived2::fn()


Caveat for beginners: beware the subtle differences in the use of pointers and references. Best to learn pointers exclusively first I would think.

• +1 for mentioning the need of the virtual destructor in the base class! – Maik Semder Mar 25 '12 at 10:08
• Oh you're right I totally forgot about references :) – David Gouveia Mar 25 '12 at 11:11