有关“隐藏”,“覆盖”的一些问题:

有如下的源代码:
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(),有点不明白了,请问:隐藏的概念到底是什么?在运行的时候,究竟是如何实现的呢?

问题较面,请高手不要见笑!
[1154 byte] By [xiaojunsyiae-快乐的小强] at [2007-12-16]
# 1
virtual void f(float x) {
cout<<"Base::f()"<<endl;

virtual void f(float x) {
cout<<"Derived::f()"<<endl;
被申明为虚函数。

pd->f(3.14f); //为动态束定

看看虚函数

blue_coco-椰子 at 2007-10-26 > top of Msdn China Tech,C/C++,C语言...
# 2
函数名字overload了!又不是virtual,那编译器只能找最近的了!和local变量覆盖global变量一样啊
# 3
虚函数是动态绑定的,其它的是在编译的时候就已经定下来了。

这里注意pb和pd的不同在于:他们的静态类型不同(即声明时左侧的类型,分别为Base 和 Derived)。

而编译的时候依据的是他们的静态类型!所以分别调用了他们自己的函数。

虚函数一定是动态绑定,他依据的是右侧的类型,对pb何pd来说都是Derived!

这样就很清楚了。
impeng-鹏 at 2007-10-26 > top of Msdn China Tech,C/C++,C语言...
# 4
以上各位的回答,好像都没有涉及到 隐藏 的实现机制哦!呵呵!再请教!!
# 5
所谓的隐藏就是派生类函数覆盖和基类同名的函数。
有以下两种情况:
1 基类函数名与派生类的函数名相同,参数不一样,无论基类是否有VIRTUAL关键字,派生类函数将隐藏基类函数。
2 基类函数名与派生类的函数名相同,参数一样,并且基类没有VIRTUAL关键字,则派生类函数将隐藏基类函数。

所谓覆盖就是派生类函数覆盖基类函数。
但有以下几个特点:
1 是基类和派生类之间的关系。
2 派生类函数和基类函数名相同,参数相同。
3 基类必须有VIRTUAL关键字。
至于它们的实现我想是通过虚拟表和树来实现,关于这方面的内容可以参考C++深度探索。
hudson-土狼 at 2007-10-26 > top of Msdn China Tech,C/C++,C语言...
# 6
hudson(胡说八道) 兄弟说的和C/C++高质量编程上的说的很相似,但是,我想知道的是如何实现的,也就是说,如何可以使 指向同一地址的指针,可以调用不同的函数?
# 7
我想你要问的是在编译器中如何实现的?!

如果是这样的话,那么:

你的基类在子类构造之前就已经构造好了(调用它自己的构造函数),即需要的东西(父类的和子类的)事实上都是存在的,而不像想象中的那样,好像只有子类的东西才被构造了。

编译器在构造一个类之前,首先要构造他的父类,即父类的构造函数会被调用!因为子类永远离不开它的父类。
impeng-鹏 at 2007-10-26 > top of Msdn China Tech,C/C++,C语言...
# 8
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.
do_do-do_do at 2007-10-26 > top of Msdn China Tech,C/C++,C语言...