Virtual Functions - Why?

Hi everyone,

I'm learning about virtual functions. Given the following code:

Base *pBase = new Derived;

My questions are: Is this the only way to utilize virtual functions? If so, why use this implementation instead of just overriding the function in the Derived class (why not just create Derived *pDerived = new Derived)? And finally, is there any way to access private data members of Derived through pBase, and what problems will this produce if a virtual member function is used in Derived that uses data members from its own class?

I've been looking around online and I can only find syntax information on virtual functions and how they're used, not really on why they are used.

Thanks!
Is this the only way to utilize virtual functions?
You can use virtual functions as other functions, this way is the only which really use virtual functions
why not just create Derived *pDerived = new Derived
You need virtual functions when you have multiple classes derived from the same base
eg:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
struct Base
{
    virtual void do_something() = 0;
};


struct Derived1 : public Base
{
    void do_something()
    {
         cout << "I'm doing something";
    }
};

struct Derived2 : public Base
{
    void do_something()
    {
         cout << "I'm doing something else";
    }
};

int main()
{
    Base *pBase = new Derived1;
    pBase->do_something();//does something
    delete pBase;
    pBase = new Derived2;
    pBase->do_something();//does something else
    delete pBase;
    return 0;
}
pBase uses the same interface ( do_something ) but the result would vary depending on which derived class object you created

is there any way to access private data members of Derived through pBase
You can access private members only on friend functions / classes. pBase would have access only to the members of Derived which are derived from Base.

what problems will this produce if a virtual member function is used in Derived that uses data members from its own class?
It wouldn't give any problem



-- My example was pointless, for something better see http://www.cplusplus.com/doc/tutorial/polymorphism/ --
I think I can give a nice example of the usefulness of base and derived classes. I'll give it a shot:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Vehicle
{
    public:
    virtual void Start() = 0;
    virtual void Stop() = 0;
    virtual void Accelerate() = 0;
    virtual float get_Speed() = 0;
}

class Car : Vehicle
{
    override void Start()
    {
        cout << "You properly started this car!";
    }
    //Something like the sort goes for the other functions.
    ...
}

class Airplane : Vehicle
{
    override void Start()
    {
        cout << "You properly started this airplane!  You rock.";
    }
    ...
}

class Helicopter : Vehicle
{
    override void Start()
    {
        cout << "You properly started this helicopter.  Is there anything you can't do??";
    }
    ...
}


Now, with those classes you can choose to create 3 different functions to start, accelerate, and stop a car, an airplane, and a helicopter respectively, OR you can do it the cool way: One function that start, accelerate, and stop any vehicle.

Because I have so much money and have a garage full of cars, airplanes, and helicopters, I want to group all of them into an array so I can have them handy. Note that this is NOT possible if you don't use polymorphism (it is possible, but it is a big fat pain in you know where).

1
2
//Declare the array of ... what?  Cars?  No.  Airplanes??  No!!  Vehicles!!
Vehicle[] myVehicles = { new Car(), new Airplane(), new Airplane(), new Car(), new Helicopter(), new Helicopter() };


If I didn't have the base Vehicle class, I could never group my garage contents into a single array.

Now, let's drive all of them:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void TestDriveThis(Vehicle *vehicle)
{
    vehicle->Start();
    float currentSpeed = 0;
    float targetSpeed = 150;
    while (currentSpeed < targetSpeed)
    {
        vehicle->Accelerate();
        currentSpeed = vehicle->get_Speed();
    }
    //You reach the target speed, now get your foot off the pedal and say hello to the ladies along the road.
    while (currentSpeed > 0)
    {
        SayHelloToNurses();
    }
    vehicle->Stop();
}

...
int main()
{
    for(int i = 0; i < 6; i++)
    {
        TestDriveThis(myVehicles[i]);
    }
    return 0;
}


Without the base class Vehicle, I wouldn't have been able to collect all of my vehicles in a single array, and I wouldn't have been able to test drive them all using the same function. Instead, I would have had to have 3 different arrays (one for cars, one for airplanes, and one for helicopters), and I would have had to have 3 different TestDriveThis() functions, again, one for cars, one for airplanes, and one for helicopters.
webJose, it would have been nice to give an example that is actually valid C++.
The language supplies some built in types (like int, float), but C++ allows you to create your own types. Object Oriented languages allow you to create new types that are based on some existing type and change the behaviour a little using inheritance.

In C++ if you want to create a new type that has methods that can be overridden by another object, you declare those methods virtual.

To answer your questions:
1. This is the only time you use virtual functions, when you want to override a function in a base class. It's a design matter which functions are virtual. You don't apply the virtual keyword at random or as you go along.

2. One of the points of OO is that you do not reimplement code already provided in the base class, you simply reuse it. It's an effort saving thing.

3. You can override almost anything in C++, but it's usually not a good idea as the constraints are there for a reason. A class can declare another class to be a friend, and that class will have unfettered access. you don't want to do this as it breaks the structure of the program and creates a program that is unmaintainable.
I think it can be summarized as follows:

A function should be declared virtual [in the base class] if you ever intend to allow derived classes to reimplement
the function AND you intend to call the function through a base class pointer/reference.
jsmith:

Where did I go wrong? I have been doing C# straight for 10 days. Did I confuse the syntax?
Nod, override isn't needed.
Ah, yes. C# keyword slip. :-( My bad.
Topic archived. No new replies allowed.