【概念】

a) 作用域

作用域有大小之分。比如全局作用域大于局部作用域,这个很显然。要强调的是另一点:基类作用域大于派生类作用域。可能有人会有疑问,这两个作用域看不见摸不到,怎么知道大小?但是其实仔细想想,这很符合现实世界的面向对象模型:鱼的作用域显然要比金鱼大,交通工具的作用域肯定要比飞机大。如果你实在理解不了,那你还是就这么记住吧。

b) 名字查找

请注意,这里的名字仅仅是指函数的名字,而不是原型!名字相同,查找即成功。这是个跟作用域密切相关的概念。名字查找符合以下的过程:

1.根据对象,指针,引用的静态版本决定哪一个函数被调用。
2.到相应的中查找,如果没有找到,则到该类的直接基类中查找,按此过程下去都没找到,报错。
3.找到,做原型检查,看调用是否正确。
4.正确,判断是否动态绑定,调用相应版本。

这个过程概括就是:先静态,后动态;作用域从小至大。

======================================================

[举例]

下面举几个例子来说明这种情况。

(1)下面这个例子说明了名字查找只根据静态类型查找(即使是指针调用,也只看指针的静态类型)。也可以从另一个角度理解这个问题:

“虚函数必须在基类和派生类中拥有同一原型”。 所以,Derived类中的func()其实已经不是虚函数了,所以其实不能提供多态的性质。当然,Derived类中仍然有虚函数指针(Derived类对象的size都是4),其中存的是base::func()。

#include <iostream>

using namespace std;

class
Base
{
public
:
    
virtual void func(double i){ cout<<"in base\n"
; }
};

class Derived : public
Base
{
public
:
    
void func(){ cout<<"in derived\n"
; }
};

int main(void
)
{
     Base b;
     Derived d;

     Base
*pb = &
d;
     Derived
*pd = &
d;

     b.func(
3.14
);
    
//b.func();    //
compile error

    
//d.func(3.14);    //compile error

     d.func();

     pb
->func(3.14
);
    
//pb->func();    //
compile error : can't find func() in Base

    
//pd->func(3.14);    //compile error : can't find func(double) in Derived

     pd->func();
}

(2)下面是《C++ Primer》书中的经典例子。

class Base
{
public
:
    
virtual int
fcn();
};

class Derived1 : public
Base
{
public
:
    
//hides Base::fcn(), this fcn(int) is not virtual

    int fcn(int);
    
//Derived1 inherits definition of Base::fcn()

};

class Derived2 : public
Derived1
{
public
:
    
int fcn(int);//nonvirtual function hides Derived1::fcn(int)

    int fcn();//redefine virtual Base::fcn()
};

请读者自行理解。




通过 Wiz 发布


posted on 2011-05-11 22:56  微型葡萄  阅读(435)  评论(0编辑  收藏  举报