Skip to main content
gamedev.net
🔒 Locked

Virtual Functions

Started by Third 7 replies 650+ views
Original Post
Third
Third
Could somebody explain how these work, and their importance? I have re-read the section in my book over and over about them but I just can't seem to grasp it. [edited by - Third on August 12, 2003 10:55:45 PM]
zygote_mm
zygote_mm
You use virtual functions so you can call methods thru interfaces.

heres a simple example:



class Vehicle
{
protected:
virtual void Accellerate()=0;
virtual void Deccellerate()=0;
};



then you have implementations of the interface:



class Car : public Vehicle
{
virtual void Accellerate(){ cout << "car accel" << endl;}
virtual void Deccellerate(){ cout << "car deccel" << endl;}
};

class Truck : public Vehicle
{
virtual void Accellerate(){ cout << "truck accel" << endl;}
virtual void Deccellerate(){ cout << "truck deccel" << endl;}
};



now you can create a class of a car and a truck using the generic interface:

Vehicle *pCar = new Car();
Vehicle *pTruck = new Truck();

and manipulate them generically:

void ManipulateVehicle(Vehicle* p)
{
p->Accellerate();
p->Deccellerate();
}


ManipulateVehicle(pCar);
ManipulateVehicle(pTruck);


BTW:
virtual functions use a lookup table to find the methods to call, so its not very fast at all, altho when used properly it can be very robust and endlessly enjoyable

Zygote-


ps:
Theres much more to ''virtual''.. i''m sure you will figure it out over time.
Vangelis
Vangelis
I have a class with a function that I would like to use as the calback procedure for a dialog, but when I send the function in through a CreateDialog or DialogBox function I get errors like.

error C2664: ''CreateDialogParamA'' : cannot convert parameter 4 from ''int (struct HWND__ *,unsigned int,unsigned int,long)'' to ''int (__stdcall *)(struct HWND__ *,un
signed int,unsigned int,long)''


The prototype for my dialog callback looks like...

BOOL CALLBACK EditDlgProc(HWND,UINT,WPARAM,LPARAM); 


and I attempt to create a dialog using it by...


DialogBox(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_EDITDLG),mainWindow,EditDlgProc); 


I''m guessing it has something to do with how member functions are called, and it involves stdcall, but I do not know how to fix it. Is there a standard way of doing this?
---------------------Ryan Bujnowicz[ vangelis ]
Third
Third
quote:
Original post by zygote_mm
You use virtual functions so you can call methods thru interfaces.

heres a simple example:



class Vehicle
{
protected:
virtual void Accellerate()=0;
virtual void Deccellerate()=0;
};



then you have implementations of the interface:



class Car : public Vehicle
{
virtual void Accellerate(){ cout << "car accel" << endl;}
virtual void Deccellerate(){ cout << "car deccel" << endl;}
};

class Truck : public Vehicle
{
virtual void Accellerate(){ cout << "truck accel" << endl;}
virtual void Deccellerate(){ cout << "truck deccel" << endl;}
};



now you can create a class of a car and a truck using the generic interface:

Vehicle *pCar = new Car();
Vehicle *pTruck = new Truck();

and manipulate them generically:

void ManipulateVehicle(Vehicle* p)
{
p->Accellerate();
p->Deccellerate();
}


ManipulateVehicle(pCar);
ManipulateVehicle(pTruck);


BTW:
virtual functions use a lookup table to find the methods to call, so its not very fast at all, altho when used properly it can be very robust and endlessly enjoyable

Zygote-


ps:
Theres much more to ''virtual''.. i''m sure you will figure it out over time.


But can''t you basically do the same thing when you override a base class member function?

Cedric
Cedric
quote:
Original post by Third
But can't you basically do the same thing when you override a base class member function?

What do you mean "override"? If you don't declare your base function as virtual, you won't get dynamic behavior. IIRC, your derived function will be "hiding" your base function instead (meaning that the base function will still be called if you have a pointer-to-base). That's a moral sin, in most cases.

Virtual functions are the basis of object oriented programming. There are plenty of ressources on the Internet already. Check the C++ FAQ Lite for a decent explanation.

Sorry if my explanations weren't too friendly, but you need to get up to par.

Cédric

EDIT: I'm not sure of the meaning of override. In C#, overriding a function requires (AFAIK) that the base function be virtual. So it would be like someone telling you to use a nail to put something into place, and you're responding "but can't I do the same thing with a hammer?"

[edited by - Cedric on August 12, 2003 12:10:42 AM]
fallenang3l
fallenang3l
quote:
Original post by Third
But can''t you basically do the same thing when you override a base class member function?



Yes, but since you''re using pointers to base class, the base class version of the method would get called. Try compiling zygote''s code with and without the virtual keyword and see the difference in behavior.
Third
Third
quote:
Original post by fallenang3l
quote:
Original post by Third
But can''t you basically do the same thing when you override a base class member function?



Yes, but since you''re using pointers to base class, the base class version of the method would get called. Try compiling zygote''s code with and without the virtual keyword and see the difference in behavior.


Oh, ok. I think I get it now. So if you need a pointer, but still want to use the overriden member functions in a derived class you must declare the member functions in the base class that are going to be overriden to be virtual? But if you don''t need a pointer, then you can just override them?(sorry if I wasn''t very clear)

Lektrix
Lektrix
If you merely redefine base class methods in your derived class (i.e. non-virtual), the method to be invoked is determined by the actual reference or pointer type (i.e. the static type of the object). For example:

class base
{
public:
...
void DoSomething()
{
std::cout << "base::DoSomething()" << std::endl;
}
...
private:
...
};

class derived : public base
{
public:
...
void DoSomething()
{
std::cout << "derived::DoSomething()" << std::endl;
}
...
private:
...
};


int main()
{
base base_obj;
derived der_obj;

base_obj.DoSomething(); // invoke base::DoSomething()

der_obj.DoSomething(); // invoke derived::DoSomething()


// here''s the important part

base& rb = der_obj;
rb.DoSomething(); // invoke base::DoSomething()


...

return 0;
}

If you use the virtual function mechanism, the method to be invoked is determined by the type of the object the reference or pointer refers to (i.e. the dynamic type of the object). For example:

class base
{
public:
...
virtual void DoSomething()
{
std::cout << "base::DoSomething()" << std::endl;
}
...
private:
...
};

class derived : public base
{
public:
...
virtual void DoSomething()
{
std::cout << "derived::DoSomething()" << std::endl;
}
...
private:
...
};


int main()
{
base base_obj;
derived der_obj;

base_obj.DoSomething(); // invoke base::DoSomething()

der_obj.DoSomething(); // invoke derived::DoSomething()


// here''s the important part

base& rb = der_obj;
rb.DoSomething(); // invoke derived::DoSomething()


...

return 0;
}


[ Google || Start Here || ACCU || STL || Boost || MSDN || GotW || MSVC++ Library Fixes || BarrysWorld || E-Mail Me ]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.