Then I have a question again. something like this:
#include <iostream>
using namespace std;
class Base
{
public:
void foo()
{
cout<<"Base."<<endl;
}
};
class Derive:public Base
{
public:
void foo()
{
cout<<"Derive."<<endl;
}
};
int main()
{
Derive d;
Base *pb=&d; //attention here
pb->foo(); //ateention here
system("pause");
return 0;
}
And the output is "Base.". Then the function rules are't work, I am confused about this, could you help me? Thanks.
Since foo
is not virtual, the function called is based on the static type (i.e., the type the pointer is declared to point at) rather than the dynamic type (the type of object to which the pointer currently refers).
There are also some trickier cases to consider. One point (on which some of the other answers are actually somewhat misleading) is that it's not really just the function name that matters, but the entire function signature. For example:
#include <iostream>
struct base {
virtual void foo() {
std::cout << "base::foo";
}
};
struct derived : base {
virtual void foo() const {
std::cout << "derived::foo";
}
};
int main(){
base *b = new derived;
b->foo();
}
Here foo
is qualified as virtual
in both the base and (seemingly redundantly the) derived classes, but the call b->foo()
still prints out base::foo
.
The const
added to the signature of derived::foo
means it no longer matches the signature of base::foo
, so instead of overriding the virtual function, we still end up with two separate functions with the same name, so derived::foo
hides base::foo
, but doesn't override it. Despite the virtual
qualification, we get static binding, so b->foo();
invokes the base function rather than the derived, even though b
points to an object of the derived
type.
As Tony D pointed out in a comment, C++11 added a new wrinkle to the language to help ensure against this happening. When you want to override a base class function, you can add the identifier override
to the function in the derived class:
struct derived : base {
virtual void foo() const override {
std::cout << "derived::foo";
}
};
With this, if there's a difference in function signature (as in the cases shown here), the compiler will produce an error message alerting you to the fact that derived::foo
is marked as override
, but doesn't actually override a function from the base class. This was, however, added in C++11, so if you're using an older compiler this feature may not be implemented (though thankfully, compilers that don't implement it are quickly fading into oblivion).
Correcting the signature in the base class to:
virtual void foo() const // ...
...will let the code compile, and produce the correct results.