问题
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();
回答1:
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
回答2:
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();
回答3:
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()
.
来源:https://stackoverflow.com/questions/13023028/virtual-functions-in-c-and-java