重载、覆盖与隐藏

 重载(overload)用于同一个类中的成员函数,其特征为:
(1)相同的范围(在同一个类中);
(2)相同的函数名字;
(3)参数不同(包括参数类型不同,或参数个数不同,或两者都不同。注意:和返回值没关系);
(4)和是否为虚函数无关。
覆盖(override)是指派生类函数覆盖基类函数,其特征为:
(1)不同的范围(分别位于派生类与基类);
(2)相同的函数名字;
(3)参数相同(即参数类型和参数个数均相同);
(4)基类函数必须是虚函数。
隐藏(hide)是指派生类的函数屏蔽了与其同名的基类函数,其特征为:
(1)不同的范围(分别位于派生类与基类);
(2)相同的函数名字;
(3)若参数不同,基类函数无virtual关键字,基类函数将会被隐藏。(因为派生类和基类不在同一范围,所以是隐藏而不是重载);
(4)若参数不同,基类函数有virtual关键字。基类函数将会被隐藏。(因为派生类和基类不在同一范围,所以是隐藏而不是重载;因为参数不同,所以是隐藏而不是覆盖);
(5)若参数相同,基类函数无virtual关键字。基类函数将会被隐藏。(因为基类函数不是虚函数,所以是隐藏而不是覆盖)。
(6)若参数相同,基类函数有virtual关键字。如果基类函数有多个重载版本,且派生类并没有重写所有的同名虚函数,当在派生类中调用函数时,基类中未被重写的虚函数将被隐藏。(当然,被重写的函数就是覆盖了)。
注意: 如果想在派生类中调用基类中的被隐藏的函数,可以在派生类中填写如下代码:using Base::Fun2;


#include <iostream.h>

class Base
{
public:
    // overload between Fun1() and Fun1(int i)
    void Fun1()
    {
        cout<<"Base::Fun1()"<<endl;
    }

    void Fun1(int i)
    {
        cout<<"Base::Fun1(int i)"<<endl;
    }

    // overload between Fun2() and Fun2(int i)
    virtual void Fun2()
    {
        cout<<"Base::Fun2()"<<endl;
    }

    virtual void Fun2(int i)
    {
        cout<<"Base::Fun2(int i)"<<endl;
    }
};

class Derive : public Base
{
public:
// using Base::Fun2;

 // overload between Fun1(int i, int j) and Fun1(int i)   
 // hide-3
    void Fun1(int i, int j)
    {
        cout<<"Derive::Fun1(int i, int j)"<<endl;
    }

 // hide-5
 void Fun1(int i)
    {
        cout<<"Derive::Fun1(int i)"<<endl;
    }

 // overload between Fun2(int i, int j) and Fun2(int i)
 // hide-4
    virtual void Fun2(int i, int j)
    {
        cout<<"Derive::Fun2(int i, int j)"<<endl;
    }

 // override Base::Fun2(int i)
 // hide-6
    void Fun2(int i)
    {
        cout<<"Derive::Fun2(int i)"<<endl;
    } 
};

void main()
{
    Derive d;
    Base *pb = &d;
    Derive *pd = &d;

    pb->Fun1();     // Base::Fun1()
    pb->Fun1(1);    // Base::Fun1(int i)
    pb->Fun2();     // Base::Fun2()
    pb->Fun2(1);    // Derive::Fun2(int i)

    cout<<endl;
    pd->Fun1(1, 2); // Derive::Fun1(int i, int j)
    pd->Fun1(1);    // Derive::Fun1(int i)
    // error: no overloaded function takes 0 parameters
    // hide-3 or hide-5 can hide this base function
    // pd->Fun1();

    pd->Fun2(1, 2); // Derive::Fun2(int i, int j)
    pd->Fun2(1);    // Derive::Fun2(int i)
    // error: no overloaded function takes 0 parameters
    // hide-4 or hide-6 can hide this base function
    // pd->Fun2();
}

附:在C#中,编译器已经可以对隐藏发出2级警告。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
DELPHI中方法的类型及其覆盖重载 1、静态方法是方法的缺省类型,对它就像对通常的过程和函数那样调用,编译器知道这些方法的地址,所以调用一个静态方法时它能把运行信息静态地链接进可执行文件,所以,静态方法速度最快,但它们却不能被覆盖来支持多态性。 2、虚拟方法和静态方法的调用方式相同。由于虚拟方法能被覆盖,在代码中调用一个指定的虚拟方法时编译器并不知道它的地址,因此,编译器通过建立虚拟方法表(VMT)来查找在运行时的函数地址。所有的虚拟方法在运行时通过VMT来高度,一个对象的VMT表中除了自己定义的虚拟方法外,还有它的祚的所有的虚拟方法,因此虚拟方法比动态方法用的内存要多,但它执行得比较快。 3、动态方法跟虚拟方法基本相似,只是它们的高度系统不同。编译器为每一个动态方法指定一个独一无二的数字,用这个数字和动态方法的地址构造一个动态方法表(DMT)。不像VMT表,在DMT表中仅有它声明的动态方法,并且这个方法需要祖先的DMT表来访问它蓁的动态方法。正因为这样动态方法比虚拟方法用的内存要少,但执行起来罗慢,因为有可能要到祚对象的DMT中查找动态法。 4、OP通过覆盖使一方法在不同的派生类间表现出不同的行为。OP中能被覆盖的方法是在声明时被标识为virtual或dynamic的方法。为了覆盖一个方法,在派生类的声明中用override代替virtual或dynamic。用了override后,编译器就会用新的方法替换VMT中原先的方法,而原先的方法也还存在,而如果用override再次声明一个静态方法,则是真正的覆盖,是用新的方法完全替换在祖先类中的同明方法。 5、方法重载的意义:比如说,你要写一个求两数商的函数(当然只是个比喻),你希望这个函数可以处理所有的数值类型,但PASCAL的运算对类型实行严格检查,你不得不用不同的程序来运算不同类型的数值,这样你就必须为每一种类型写一个同样功能的函数,并使用不同的函数名,坏处我想你是知道的。而重载却可以解决这个问题,同样的函数名,编译器可以用不同的形参类型决定调用哪个函数。Top dynamic和virtual的不同之处 delphi动态虚拟覆盖重载重定义的区别 (www.ip8000.com www.sql8.net)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值