Advertisement

Virtual Methods

Started by March 04, 2000 10:15 PM
2 comments, last by Fredric 24 years, 7 months ago
Once again, my C++ book has failed to teach my a topic correctly. The author goes over Virtual Methods. He shows me it through code, but gives it ZERO explanation on what virtual methods actually are. In fact, the following is the ONLY description of what a virtual method is: '' On line 11 of the text, Mammal is provided with a virtual method- Speak()'' that''s it. What I''m asking from you people is a brief description of a virtual method, how it works, and how I can use it. If any of you could do that, it would be supherb! PS- I''m getting a new C++ book for my b-day (March 13th), so, enough of this lousy methods of teaching me C++... Programming::~Fredric(const Annoy_Ance)
3D Math- The type of mathematics that'll put hair on your chest!
Okay, let me try to explain it then. A virtual function is a way to allow you to declare a function in a base class that can be redefined in each derived class. For instance, you might have a class Employee, and derived classes of Secretary and Programmer. You can define a virtual function in Employee such as printDetails that will print out the employees' id number and salary, for instance, and then also define the function printDetails (with the same input parameters and probably the same output parameter, if any) in Secretary or Programmer. The compiler will make sure and call the correct printDetails method. A virtual function must have some implementation in the base class. A pure virtual function will not have an implementation in the base class, and thus any derived classes must either have the function again as a pure virtual function or implement the function.

I don't know if that is entirely clear. If not, reply and I'll try to provide more info.

Cya,
Dave

Edited by - Dave Myers on 3/4/00 10:40:49 PM
Advertisement
In a nutshell, virtual functions are functions that are always called when a function of that name is called, no matter what pointer type you use to call it. That is if I have a class A with a virtual function int hello(void), and I create derived class B from A, and redefine int hello(void), I can cast a pointer to an object B as a pointer to object A and still call hello() on the pointer and have it perform the right hello() function.

In code:
class A {  public:    int hello1(void) { return 1; }     virtual int hello2(void) { return 1; }}class B : public class A {  public:    int hello1(void) { return 2; }    virtual int hello2(void) { return 2; }}int main() {  A * pointer;  B object;  pointer = &object  int i;  i = pointer->hello1(); // i = 1 because it calls A''s hello1()  i = pointer->hello2(); // i = 2 because it calls B''s hello2()} 



Here''s the text from the C++ Builder 4.0 Help file on virtual functions, in case I wasn''t clear.

quote:
virtual functions allow derived classes to provide different versions of a base class function. You can use the virtual keyword to declare a virtual function in a base class. By declaring the function prototype in the usual way and then prefixing the declaration with the virtual keyword. To declare a pure function (which automatically declares an abstract class), prefix the prototype with the virtual keyword, and set the function equal to zero.

virtual int funct1(void);       // A virtual function declaration.

virtual int funct2(void) = 0;   // A pure function declaration.
virtual void funct3(void) = 0 { // This is a valid declaration.
   // Some code here.

   };

Note: See Abstract classes for a discussion of pure virtual functions.

When you declare virtual functions, keep these guidelines in mind:

They can be member functions only.
They can be declared a friend of another class.
They cannot be a static member.

A virtual function does not need to be redefined in a derived class. You can supply one definition in the base class so that all calls will access the base function.

To redefine a virtual function in any derived class, the number and type of arguments must be the same in the base class declaration and in the derived class declaration. (The case for redefined virtual functions differing only in return type is discussed below.) A redefined function is said to override the base class function.

You can also declare the functions int Base::Fun(int) and int Derived::Fun(int) even when they are not virtual. In such a case, int Derived::Fun(int) is said to hide any other versions of Fun(int) that exist in any base classes. In addition, if class Derived defines other versions of Fun(), (that is, versions of Fun() with different signatures) such versions are said to be overloaded versions of Fun().

Virtual function return types

Generally, when redefining a virtual function, you cannot change just the function return type. To redefine a virtual function, the new definition (in some derived class) must exactly match the return type and formal parameters of the initial declaration. If two functions with the same name have different formal parameters, C++ considers them different, and the virtual function mechanism is ignored.

However, for certain virtual functions in a base class, their overriding version in a derived class can have a return type that is different from the overridden function. This is possible only when both of the following conditions are met:

The overridden virtual function returns a pointer or reference to the base class.
The overriding function returns a pointer or reference to the derived class.

If a base class B and class D (derived publicly from B) each contain a virtual function vf, then if vf is called for an object d of D, the call made is D::vf(), even when the access is via a pointer or reference to B. For example,

struct X {}; // Base class.

struct Y : X {}; // Derived class.

struct B {
   virtual void vf1();
   virtual void vf2();
   virtual void vf3();
   void f();

   virtual X* pf();
// Return type is a pointer to base. This can
   //  be overridden.

   };
class D : public B {
public:

   virtual void vf1(); // Virtual specifier is legal but redundant.
   void vf2(int); // Not virtual, since it''s using a different
  //  arg list. This hides B::vf2().
// char vf3(); // Illegal: return-type-only change!
   void f();
   Y*   pf(); // Overriding function differs only
    //  in return type. Returns a pointer to
  //  the derived class.

   };
void extf() {

   D d; // Instantiate D
   B* bp = &d // Standard conversion from D* to B*
   // Initialize bp with the table of functions
// provided for object d. If there is no entry for a
   // function in the d-table, use the function
      //  in the B-table.
   bp–>vf1();  // Calls D::vf1
   bp–>vf2();  // Calls B::vf2 since D''s vf2 has different args
   bp–>f();    // Calls B::f (not virtual)

   X* xptr = bp–>pf(); // Calls D::pf() and converts the result
    //  to a pointer to X.
   D* dptr = &d
   Y* yptr = dptr–>pf(); // Calls D::pf() and initializes yptr.
    //  No further conversion is done.

   }

The overriding function vf1 in D is automatically virtual. The virtual specifier can be used with an overriding function declaration in the derived class. If other classes will be derived from D, the virtual keyword is required. If no further classes will be derived from D, the use of virtual is redundant.

The interpretation of a virtual function call depends on the type of the object it is called for; with nonvirtual function calls, the interpretation depends only on the type of the pointer or reference denoting the object it is called for.

virtual functions exact a price for their versatility: each object in the derived class needs to carry a pointer to a table of functions in order to select the correct one at run time (late binding).

Alright, thanks.. I got it now. I thank both of you for helping me out with this! It wasn''t hard at all (for now at least! )

Programming::~Fredric(const Annoy_Ance)
3D Math- The type of mathematics that'll put hair on your chest!

This topic is closed to new replies.

Advertisement