小析override & overload

来源:互联网 发布:淘宝网足球 编辑:程序博客网 时间:2024/04/29 22:04
一、overload,译为重载,是C++提供的一种处理函数重名的机制。

void f(float) { ... }
void f(int) { ... }

在C中上面代码不能通过编译,而在C++中却可以。这是因为C++编译器根据参数为每个重载函数产生不同的内部标识符,也就是说参数表是判断函数相同与否的标志。但是,我们会很自然地想到为什么不用返回值作为区分标志呢?请看下面的例子:

void f() { ... }
int f() { ... }

如果这样调用:

int a = f();

我们很容易判断出其调用的是int f(),但是不要忘记了,我们可以忽略掉返回值,如:

f();

上面的函数调用到底是调用的哪个函数,是void f()还是int f(),于是二义性产生了。
能够称得上overload还得有一个条件:必须在同一个域中。

void f(int);
void g()
{
   void f(double);
   f(12);
}

上面代码中,void f(int)和void f(double)构不成重载,由于void f(int)在全局域声明,而void f(double)是在局部域声明,根据C++编译规则void f(double)会隐藏掉void f(int)。

二、override,译为覆盖或重写,是C++中用于实现多态(“用基类的指针或引用操纵多个子类对象”的能力)的一种手段,该手段通常体现在类继承的行为当中。override要求两个函数的函数头相同(即:返回类型、函数名、参数表)。

1、对基类非virtual函数的override。

class Base
{
public:
    void f(int) { ... }
};
class Derived : public Base
{
public:
    void f(int) { ... }
};

当我们进行如下调用的时候:

Base* a = new Derived;
a->f(12);

到底调用的是哪个函数呢?回答是Base::f。原因是:当把Derived对象的地址赋给Base指针的时候,实际上进行了一个隐式类型转换(对象切片),所以只能调用到基类的f成员了。

2、对基类virtual函数的override。

class Base
{
public:
    virtual void f(int) { ... }
};
class Derived : public Base
{
public:
    virtual void f(int) { ... }
};

当我们进行如下调用的时候:

Base* a = new Derived;
a->f(12);

又调用哪个函数呢?答案是:Derived::f。为什么一个关键字之差会产生不同的结果呢?通过这种方式我们实现了所谓的“用基类的指针或引用操纵多个子类对象”从而实现了多态。实际上,“virtual”关键字实现了一种“动态绑定”技术,它告诉编译器建立一张虚函数表,然后在运行时根据具体的对象类型调用不同正确的成员函数。 
原创粉丝点击