有关“隐藏”,“覆盖”的一些问题:
有如下的源代码:
class Base
{
public:
virtual void f(float x) {
cout<<"Base::f()"<<endl;
}
void g(float x) {
cout<<"Base::g()"<<endl;
}
void h(float x) {
cout<<"Base::h()"<<endl;
}
};
class Derived:public Base
{
public:
virtual void f(float x) {
cout<<"Derived::f()"<<endl;
}
void g(int x) {
cout<<"Derived::g()"<<endl;
}
void h(float x) {
cout<<"Derived::h()"<<endl;
}
};
void main(void)
{
Derived d;
Base *pb=&d;
Derived *pd=&d;
pb->f(3.14f);
pd->f(3.14f);
pb->g(3.14f);
pd->g(3.14f);
pb->h(3.14f);
pd->h(3.14f);
system("pause");
}
运行后得到的结果:
Derived::f()
Derived::f()
Base::g()
Derived::g()
Base::h()
Derived::h()
不明白的是:
1、pd,pb都指向同一个地址,理论上来说,应该得到的结果应该是完全一样的。丛书上的讨论上来说,这是因为派生类的g(),h()隐藏了基类的g(),h(),有点不明白了,请问:隐藏的概念到底是什么?在运行的时候,究竟是如何实现的呢?
问题较面,请高手不要见笑!
virtual void f(float x) {
cout<<"Base::f()"<<endl;
virtual void f(float x) {
cout<<"Derived::f()"<<endl;
被申明为虚函数。
pd->f(3.14f); //为动态束定
看看虚函数
虚函数是动态绑定的,其它的是在编译的时候就已经定下来了。
这里注意pb和pd的不同在于:他们的静态类型不同(即声明时左侧的类型,分别为Base 和 Derived)。
而编译的时候依据的是他们的静态类型!所以分别调用了他们自己的函数。
虚函数一定是动态绑定,他依据的是右侧的类型,对pb何pd来说都是Derived!
这样就很清楚了。
所谓的隐藏就是派生类函数覆盖和基类同名的函数。
有以下两种情况:
1 基类函数名与派生类的函数名相同,参数不一样,无论基类是否有VIRTUAL关键字,派生类函数将隐藏基类函数。
2 基类函数名与派生类的函数名相同,参数一样,并且基类没有VIRTUAL关键字,则派生类函数将隐藏基类函数。
所谓覆盖就是派生类函数覆盖基类函数。
但有以下几个特点:
1 是基类和派生类之间的关系。
2 派生类函数和基类函数名相同,参数相同。
3 基类必须有VIRTUAL关键字。
至于它们的实现我想是通过虚拟表和树来实现,关于这方面的内容可以参考C++深度探索。
Function/method hiding is done at compile time by compiler. Here is how it works. Compiler searches from the class of the variable (not the class of the variable value, for example, in the case of a pointer or reference, it is the pointer/reference type class not the pointed object's class), if it finds a match in method name, it compares the parameters. If they match, then construct the call. Otherwise emit error message and does not search the inheritance tree to see if the method is defined in parent classes. If it does not find any matching method name, it searches the inheritance tree until either a name match is found or end of inheritance tree.
For example:
class A {
public:
void foo();
void boo();
};
class B:public A
{
public:
void foo(int);
};
B b;
b.foo(); //compilation error, parameter in B::foo(int) does not match. It does not search the inheritance tree to find the matching A::foo().
b.boo(); //OK, because no name match in class B, search go on to class A and find A::boo();
b.foo(1); //OK, obviously.
Some book/people might use the term "function searching scope". So, the "search scope" is from the entry class till either a name match or end of inheritance tree.