views:

146

answers:

5

In my C++ program:

#include<iostream.h>

class A
{
    public:
    virtual void func()
    {
         cout<<"In A"<<endl;
    }
};

class B:public A
{
    public:
    void func()
    {
        cout<<"In B"<<endl;
    }
};

class C:public B
{
    public:
    void func()
    { 
        cout<<"In C"<<endl;
    }
};  

int main()
{
    B *ptr=new C;
    ptr->func();
}

the statement should call B::func(). However, the function, C::func() is called. Please throw some light on this. Once the virtual keyword is removed in 'class A', this does not happen anymore.

+3  A: 

For the basics you should read C++ FAQ Lite on Virtual Functions.

A virtual function allows derived classes to replace the implementation provided by the base class. The compiler makes sure the replacement is always called whenever the object in question is actually of the derived class, even if the object is accessed by a base pointer rather than a derived pointer. This allows algorithms in the base class to be replaced in the derived class, even if users don't know about the derived class.

Marcin Gil
But, doesnt the fact that I have redefined func() in class B take away the virtual nature of the function?
Avik Banerjee
Read the FAQ :) If you make a method virtual within base class it is not necessary to put `virtual` keyword in any derived class - it will be virtual anyway.If you *overloaded* the function as with different parameters - then it will work non-virtually.
Marcin Gil
+7  A: 

Once declared virtual function will be virtual in all derived classes (no matter if you explicitly specify it or not). So func() is virtual in A, B and C classes.

begray
+1  A: 

the statement should call B::func()

Since the pointer points to an object of class C, it will call the function in class C.

Virtual functions lead to run time binding, meaning that the function to be called will be decided based on the object pointed to by the pointer, not the type of pointer declared at the compile time.

Amarghosh
+1  A: 

This is the essence of polymorphism. The main function doesn't need to know the ptr is actually pointing to an object of class C, it only needs to know that the available interface is at least that which is defined in class B (which is why you declare it as B *ptr, if you needed functions specific to C, you would have to do C *ptr).

When you say the function is virtual in B, it means that it may be overloaded by a subclass, and the compiler generates code which looks for this alternate implementation. In this case, it finds it in C (the actual details might differ from compiler to compiler, but most compilers let the object carry a table with it, the so called virtual table, mapping func() to a specific implementation), and calls that one.

If there's no virtual keyword, this tells the compiler that there can't be an alternative implementation, and hard-links it to the B-implementation directly.

roe
A: 

If you would have done:

B *obj = new B;

Then it would have called B::func().
To atchive the functionallity you are expecting you should remove the new implementation of func in C.
If you use a virtual function you actually say I don't know what type of object I have inside as long as it's from the same family of objects (In this A is the "father" of the "family"). All you know is that each member of the "family" has to do a different job for a specific part. For instance:

class Father
{
public:
  virtual void func() { cout << "I do stuff"; }
};
class Child : public Father
{
public:
  virtual void func() { cout << "I need to do something completely different"; }
};

int main()
{
  Father *f = new Father;
  f->func(); // output: I do stuff
  delete f;
  f = new Child;
  f->func(); // output: I need to do something completely different
  delete f;
}
the_drow