Virtual Functions in C++ and Java
Asked Answered
C

3

4

I have been reading about Virtual functions and found,

VF are used in polymorphism of an inherited class.

So , if a class and derived class both have the same function name, VF binds the appropriate function to the function call.

i.e. If the function in question is designated virtual in the base class then the derived class's function would be called. If it is not virtual, the base class's function would be called.

In Java by default: all functions are Virtual C++: Non-virtual and can be made Virtual in Java by using final, private access modifier while in C++ using Virtual keyword to make a function virtual.

Based on the above theory, i wrote the code:

#include <iostream>

class base{
    public : 
        virtual void function1(){
            std::cout<<"BaseVirtual"<<std::endl;
        }

        void function2(){
            std::cout<<"Base NonVirtual"<<std::endl;
        }
};


class derieved: public base
{
    public : 
        void function1(){
            std::cout<<"Derieved Virtual"<<std::endl;
        }

        void function2(){
            std::cout<<"Derieved NonVirtual"<<std::endl;
        }
};



int main()
{
    base b1;
    derieved d1;

    b1.function1();
    b1.function2();

    d1.function1();
    d1.function2();    

}

Now based on the fact, if its a virtual function then only derived class function is called, my output for the above program should be:

BaseVirtual
Base NonVirtual
Derieved Virtual
Base NonVirtual

however, it came out to be:

BaseVirtual
Base NonVirtual
Derieved Virtual
Derieved NonVirtual

which must be right of course. So my question is the output totally violates the statement If the function in question is designated virtual in the base class then the derived class's function would be called. If it is not virtual, the base class's function would be called. for the call:

  d1.function2();    
Cortes answered 23/10, 2012 at 3:10 Comment(5)
That quote you cited from wikipedia needs to be edited or removed.Hoofbeat
Wow.. how do you know its from Wikipedia.. anyways.. thanks for clearing up the doubt..i should never rely for Wikipedia..Cortes
"and can be made Virtual in Java by using final, private access modifier" doesn't make any sense. If someone will provide the Wikipedia link I will fix it.Ironing
In fact I fixed this Wiki page, comments here or there welcome, but it doesn't contain the text I quoted above, pointers still welcome.Ironing
@EJP thank you Sir.. you made world a better place :)Cortes
P
9

Yes.. the role of virtual comes into picture if and only if you have are trying to access the derived class object with a base class pointer.

With you example:-

#include <iostream>

class base{
    public : 
        virtual void function1(){
            std::cout<<"BaseVirtual"<<std::endl;
        }

        void function2(){
            std::cout<<"Base NonVirtual"<<std::endl;
        }
};


class derieved: public base
{
    public : 
        void function1(){
            std::cout<<"Derieved Virtual"<<std::endl;
        }

        void function2(){
            std::cout<<"Derieved NonVirtual"<<std::endl;
        }
};



int main()
{
    base *b1;
    derieved d1;

    b1=&d1;

    b1->function1();
    b1->function2();    
    return 0;
}

output:-

Derieved Virtual
Base NonVirtual
Pawsner answered 23/10, 2012 at 3:34 Comment(0)
C
4

Right now, you're creating one object each of base and derived, and then invoking function1 and function2 directly on those objects. Under these conditions, virtual (or lack thereof) makes no difference at all.

At least in C++, for virtual to mean anything, you need to be working with a pointer (or reference) to a base class that's referring to an object that may be either the base or the derived class:

base *b2 = &d1;

// invoke non-virtual function. Inovkes base::function1, because we're using 
// pointer to base.
b2->function1(); 

// invoke virtual function. Invokes derived::function2 because the pointee object
// is a derived.
b2->function2();

This is particularly useful if you have (for example) a collection of pointers to objects, where those the objects those pointers refer to may be any of several different types. One of the classic examples is a base shape class, with line, circle, square, etc. derived from it. When you invoke the draw member of each, each draws its own shape. In this particular case, your base class is probably an abstract base class -- the draw member is declared "pure virtual", meaning you can't create an object of the base shape class, and to create an instance of a derived class, that has to override the draw member function:

class shape {
public:
    virtual void draw() = 0;
};

class circle : public shape { 
public:
    virtual void draw() { /* draw itself */ }
};

Then, in your drawing program, you have a collection of (pointers to) shapes the user has created, and to draw them all, you just walk through the collection and tell each to draw itself. The higher level code doesn't need to know or care whether a particular shape is a circle, square, triangle, etc.

for (int i=0; i<shapes.size(); i++)
    shapes[i]->draw();
Carnegie answered 23/10, 2012 at 3:19 Comment(1)
@FredLarson: Yup -- was editing that (and a bit more) in as you commented. Thanks though.Carnegie
L
1

Polymorphism in C++ requires utilizing pointers. If you change your example to:

base *b1 = new base();
base *d1 = new derived();

This will actually utilize the virtual mechanism. However, you seem to be confused with the basic ideas behind polymorphism. If you define a class as derived, of course it will call functions defined in the derived class, and likewise with base.

Edit: To make this more explicit, here's the output and an explanation:

b1->function1(); //Will call base::function1()
b1->function2(); //Will call base::function2()
d1->function1(); //Will call derived::function1()
d2->function2(); //Will call derived::function2()

All polymorphism/virtual calls do is allow you to treat a derived pointer as a base type, while calling the (correct) derived functions on it. So if you had another function such as:

void foo(base& b)
{
    b.function1();
}

Then passing b1 will call base::function1(), passing d1 will call derived::function1().

Lippmann answered 23/10, 2012 at 3:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.