问题
I am learning c++ and am learning about the virtual keyword. I have scoured the internet trying to understand it to no avail. I went into my editor and did the following experiment, expecting it to print out the base message twice (because I was under the impression that the virtual keyword is needed to override functions). However, it printed out two different messages. Can someone explain to me why we need the virtual keyword if we can simply override functions and still seemingly get polymorphic behavior? Perhaps someone can help me and other people in the future understand virtual vs. overriding. (The output I am getting is "I am the base" followed by "I am the derived").
#include <iostream>
using namespace std;
class Base{
public:
void printMe(){
cout << "I am the base" << endl;
}
};
class Derived: public Base{
public:
void printMe(){
cout << "I am the derived" << endl;
}
};
int main() {
Base a;
Derived b;
a.printMe();
b.printMe();
return 0;
}
回答1:
Consider the following example. The important line to illustrate the need for virtual
and override
is c->printMe();
. Note that the type of c
is Base*
, however due to polymorphism it is correctly able to call the overridden method from the derived class.
#include <iostream>
class Base{
public:
virtual void printMe(){
std::cout << "I am the base" << std::endl;
}
};
class Derived: public Base{
public:
void printMe() override {
std::cout << "I am the derived" << std::endl;
}
};
int main() {
Base a;
Derived b;
a.printMe();
b.printMe();
Base* c = &b;
c->printMe();
return 0;
}
The output is
I am the base
I am the derived
I am the derived
回答2:
With the code you have, if you do this
Derived derived;
Base* base_ptr = &derived;
base_ptr->printMe();
What do you think happens? It will not print out I am the derived
because the method is not virtual, and the dispatch is done off the static type of the calling object (i.e. Base
). If you change it to virtual the method that is called will depend on the dynamic type of the object and not the static type.
回答3:
override
is a new keyword added in C++11.
You should use it because:
the compiler will check if a base class contains a matching
virtual
method. This is important since some typo in the method name or in its list of arguments (overloads are allowed) can lead to the impression that something was overridden when it really was not.if you use
override
for one method, the compiler will report an error if another method is overridden without using theoverride
keyword. This helps detect unwanted overrides when symbol collisions happen.virtual
doesn't mean "override". In class doent use "override" keyword than to override a method you can simply write this method omitting "virtual" keyword, override will happen implicitly. Developers were writingvirtual
before C++11 to indicate their intention of override. Simply putvirtual
means: this method can be overridden in a subclasses.
回答4:
You're not seeing the behaviour here because you've declared b
to be of type Derived
so the compiler knows what functions to use. In order to expose why virtual
is necessary you need to mix things up:
int main() {
Base a;
Base *b = new Derived();
a.printMe();
b->printMe();
delete b;
return 0;
}
Now b
is of type Base*
which means it's going to use the functions on Base
plus whatever's in the virtual function table. This breaks your implementation. You can fix it by properly declaring things virtual
.
回答5:
I think your question is why would someone use a Base class pointer to call derived class at all in the program.
One such case is when you want to have a common function for all the derived class in your program. You don't want to create same functions with different derived class type argument. See below
#include<iostream>
using namespace std;
class Base{
public:
virtual void printfunc() { cout<<"this is base class";};
};
class Derived:public Base{
public:
void printfunc(){cout<<"this is derived class";};
};
void printthis(Base *ptr)
{
ptr->printfunc();
}
int main()
{
Derived func;
printthis(&func);
return 0;
}
来源:https://stackoverflow.com/questions/45357671/c-virtual-keyword-vs-overriding-function