Archived

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

Third

Virtual Functions

Recommended Posts

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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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)

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Virtual means that the method binds to the object''s type. Otherwise it binds to the class. So overriding will not help in all cases cause it will choose the method that''s in the class. The examples above should clearify.

/__fold

Share this post


Link to post
Share on other sites
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 ]

Share this post


Link to post
Share on other sites