C++ 和 Delphi 的函数覆盖(Override)与重载(overload)

原创 2003年12月19日 23:14:00

C++ 和 Delphi 的函数覆盖(Override)与重载(overload)

Spacesoft【暗夜狂沙】

在面向对象编程中,当子类继承了来自基类的函数后,子类有可能需要对其中的一些函数作出与基类不同处理,比如:

class CHuman
{
public:
    void SayMyName()//打印出对象的姓名
    {
        cout << "Hi, I am a human" << endl;
    } 
};

那么很明显,假如他的子类有一个同名、同参数和返回值(一句话,一摸一样)的函数SayMyName,它会调用哪个函数呢?比如现在有一个class CMark

class CMark: public CHuman
{
public:
    void SayMyName()
    {
        cout << "Hi, I am mark" << endl;
    }
};

那么我们要问,下面的程序段:

CHuman *pH = new CMark;
 
if (pH)
    pH->SayMyName();
else
    cout << "cast error! " << endl;

delete pH;
pH = NULL;

要打印出来的,真的是我们想要的Hi, I am mark 吗?

不是。它输出了Hi, I am a human。这很糟糕,当我们指着一个人要他说出自己的名字的时候,他却告诉我们他“是一个人”,而不是说出自己的名字。出现这样的问题原因在于,用基类的指针指向公有派生类,可以访问派生类从基类中继承的成员函数。但如果派生类中也有同名的函数,则结果仍然是访问基类的同名函数,而不是派生类本身的函数。而事实上,我们希望的是由一个对象的真实类型来决定到底该调用这些同名函数中的哪一个,就是说,这样的决议是动态(Dynamic)的。或者我们可以说,我们希望当一个对象是子类型时,它的同名函数在子类中的实现覆盖(override)掉基类的实现。

我们先从C++对这个问题的处理说起。

这是C++中比较典型的多态的例子,C++用虚函数来实现这样的多态。具体点说,就是使用virtual 关键字来将函数说明成虚函数,在上一个例子中就是应该声明成:

class CHuman
{
public:
    virtual void SayMyName()//打印出对象的姓名
    {
        cout << "Hi, I am a human" << endl;
    } 
};

这样,其他的代码还是那个老样子,但是我们的CMark 已经知道怎么说自己的名字了。CMark 的SayMyName()函数是否加了virtual 关键字的说明并没有关系,因为根据C++语法的规定,因为它覆盖了CHuman 的同名函数,它自己也就成为virtual 的了。至于为什么一个virtual 关键字有那么神奇的效果呢?C++ FAQ Lite 对此是这样说明的: 在C++中,“虚成员函数是动态确定的(在运行时)。也就是说,成员函数(在运行时)被动态地选择,该选择基于对象的类型,而不是指向该对象的指针/引用的类型”。于是我们的pH就发现自己其实指向的是一个CMark类型的对象,而不是自己的类型所声明的CHuman,所以它聪明的调用了CMark的SayMyName。


而Delphi 就是用override 关键字来说明函数覆盖的。被覆盖的函数必须是虚(virtual)的,或者是动态(dynamic)的,也就是说该函数在声明时应该包含这两个指示字中的一个,比如:

procedure Draw; virtual;

在需要覆盖的时候,只需要在子类中用override 指示字重新声明一下就可以了。

procedure Draw; override;

在语法上来说,声明为 virtual和 dynamic是等价的。它们的差别在于,前者在实现上对速度进行了优化,而后者对代码大小进行了优化。

假如基类和子类都含有同一个函数名和参数,并且在子类中不加override 指示字呢?这在语法上也是正确的。这意味着子类的函数同名实现把基类的实现隐藏(hide)掉了,尽管这二者在派生类中都存在。那么就回到了本文开头的第一个例子说明的情况:当我们指着一个人要他说出自己的名字的时候,他却告诉我们他“是一个人”,而不是说出自己的名字。

值得注意的是,与我们在C++ 中常常不加区分的把覆盖一个函数和重载一个函数通称为重载不同,在Delphi 中,只有重载(overload) 才是我们平时所说的重载,被重载的函数依然存在,依靠参数来决定到底调用那个实现。当然,当overload掉的函数和基类的函数参数相同时,基类的实现就被hide掉了,就像上面提到的一样。而覆盖(override)则是把让被覆盖的函数不可见了,确确实实的"覆盖"掉了,原来的实现就不见了。基于这样的原因,许多文章甚至一些书都错误的把override翻译成重载,笔者认为并不合适。

欢迎光临作者的个人主页:http://www.mrspace.net/

JAVA中的基础-----重载与重写(覆盖)的区别:overload与override

JAVA中多态的实现机制主要通过overload和override实现。 1)方法的重载:简言之,就是指同一个类有多个同名的方法,这些方法拥有不同的参数(同名不同参)。可以认为是类中方法的多态性,也称...
  • Emira_J
  • Emira_J
  • 2016年04月20日 10:21
  • 688

delphi中对override(重写)和overload(重载)的一些看法

 重写就是用现在的方法覆盖了继承过来的方法,重载就是在不改变继承过来的方法的基础上重新添加一个方法名字一样,但参数或返回值是不一样的。下面举个例子:unit Unit1;interfacetype T...
  • xiao_jun_0820
  • xiao_jun_0820
  • 2008年03月01日 18:36
  • 5474

override overload reintroduce的区别(delphi)

 1、override overload reintroduce的中文叫法是什么?   override:覆盖;overload:重载;Reintroduce:重定义 2、在子类中override或o...
  • honglixx
  • honglixx
  • 2008年12月28日 00:25
  • 4493

C++重写(override)、重载(overload)、重定义(redefine)以及虚函数调用机制【个人总结】

对于C++中经常出现的函数名称相同但是参数列表或者返回值不
  • loveRooney
  • loveRooney
  • 2014年07月30日 22:49
  • 4598

重载overlord与重写override的区别

重写只存在于子类与父类中,重载存在于一个类中。具体区别如下: 一、重写(override)override是重写(覆盖)了一个方法,以实现不同的功能。一般是用于子类在继承父类时,重写(重新实现)父类...
  • cf643487053
  • cf643487053
  • 2016年12月07日 10:28
  • 1143

C# 重载(overload)与重写(override)

1 重写(override) 重写(overload)指子类方法对基类虚方法的重写。当基类中的方法被声明为虚方法(使用关键字virtual),该方法可以在任何子类中被重写。若子类需要使用父类中原有的...
  • tiana0
  • tiana0
  • 2013年11月17日 13:29
  • 3056

java中方法重写(Override)与方法重载(Overload)的区别

虽然知道方法重写与方法重载,但总是会忘记具体的区别以及一些细节,所以干脆就写一篇博客记录下来吧。 方法重写(Override):        在Java中,子类可继承父类中的方法,而不需要重新编写相...
  • BeauXie
  • BeauXie
  • 2016年10月31日 20:16
  • 1817

重写(overwrite)、重载(overload)和覆盖(override)三者之间的区别

关于这三者之间,有很多书都说方法的重载就是方法的重写,也有很多书将两者加以区分,当然,也有很多书将覆盖和重载合并。正所谓人言可谓,我现在都开始怀疑我以前认为的两者说是不是正确的,当然,我不是认为两者说...
  • liuweishikong
  • liuweishikong
  • 2012年12月04日 22:03
  • 5775

C++ override overload 的区别

        override是指在不同作用域中,多个函数原型完全一样,而实现却不同的函数。在C++中,经常发生在类的继承中。当基类中的某个方法是virtual或pure virtual函数时(当然...
  • zztfj
  • zztfj
  • 2008年07月09日 10:14
  • 6639

delphi-多态(overload,override)与接口(interface)

转(智在居士草堂)先来聊聊重载问题(也叫超载,总之是那个Overload)吧。在同一个类中,出现多个同名的方法的现象就是Overload。联系起上面提到的兄弟俩,我想这更好理解。他们从外观上是相似的,...
  • qhmao
  • qhmao
  • 2007年05月12日 10:09
  • 4193
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++ 和 Delphi 的函数覆盖(Override)与重载(overload)
举报原因:
原因补充:

(最多只允许输入30个字)