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

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情
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翻译成重载,笔者认为并不合适。
 
C++头文件转Delphi工具:原理、实现跨语言接口实践 在Windows桌面开发领域,跨语言调用是常见的工程需求,尤其是C++Delphi之间的互操作。其核心原理在于理解两种语言在数据类型、内存布局函数调用约定上的差异,并建立准确的映射关系。这涉及到对应用程序二进制接口(ABI)的深入掌握,包括结构体对齐、指针传递名称修饰等底层细节。从技术价值看,可靠的自动转换工具能极大提升开发效率,减少手动绑定易引入的错误,保障项目的稳定性可维护性。典型的应用场景包括集成硬件厂商的C++ SDK、调用高性能算法库,或在遗留系统中复用Delphi的界面框架。本文通过解析 阅读详情

相关推荐

Delphi中用友华表Cell函数的高级自定义技巧

UFTable控件是用友华表控件中的核心组件之一,其主要功能是提供一个类似于数据库表的可视化界面。它允许开发者在Delphi应用程序中轻松地实现复杂的表格数据处理展示。控件的基本功能包括但不限于:单元格数据的展示编辑列的自定义排序筛选数据行的新增、删除编辑数据的导入导出操作这些功能为开发者提供了丰富的表格操作接口,大大简化了表格数据处理的复杂性。通过UFTable控件,开发者能够快速地构建出既美观又功能强大的数据管理界面。

weixin_36299472的博客 1099

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

重写就是用现在的方法覆盖了继承过来的方法,重载就是在不改变继承过来的方法的基础上重新添加一个方法名字一样,但参数或返回值是不一样的。 下面举个例子: unit Unit1; interface type TStudent=class private //... public //... procedure test; implementation procedure test; begin showmessage('我是父亲

黑鹰 933

delphi动态虚拟覆盖重载重定义的区别

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 dynamicvirtual的不同之处 delphi动态虚拟覆盖重载重定义的区别 (www.ip8000.com www.sql8.net)

Delphi重载覆盖,多态

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34393428的博客 416

Delphi 的 reintroduce继承父类但是要重载构造函数

/Reintroduce用于重新发布方法, 通常用于继承时, //如果要覆盖的方法是静态方法, 或是需要修改方法的参数等, 必须用Reintroduce进行重发布. //对于Virtual或Dynamic方法, 可以直接用Override进行覆盖. ///////来自[https://www.cnblogs.com/del/archive/2008/06/23/1228562.html] ...

qq_25235869的博客 482

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

C++ Delphi函数覆盖(Override)重载(overload)Spacesoft【暗夜狂沙】在面向对象编程中,当子类继承了来自基类的函数后,子类有可能需要对其中的一些函数作出基类不同处理,比如:class CHuman{public:    void SayMyName()//打印出对象的姓名    {        cout     } };那么很明显,假如

Spacesoft的专栏 1900

谈谈重载overload覆盖override隐藏

这三个概念都是OO中的多态有关系的。如果单是区别重载覆盖这两个概念是比较容易的,但是隐藏这一概念却使问题变得有点复杂了,下面说说它们的区别吧。 重载是指不同的函数使用相同的函数名,但是函数的参数个数或类型不同。调用的时候根据函数的参数来区别不同的函数覆盖(也叫重写)是指在派生类中重新对基类中的虚函数(注意是虚函数)重新实现。即函数参数都一样,只是函数的实现体不一样。隐藏是指派

裸奔人生 745

重载(overload)覆盖(override)隐藏

重载overload)用于同一个类中的成员函数,其特征为:(1)相同的范围(在同一个类中);(2)相同的函数名字;(3)参数不同(包括参数类型不同,或参数个数不同,或两者都不同。注意:返回值没关系);(4)是否为虚函数无关。覆盖override)是指派生类函数覆盖基类函数,其特征为:(1)不同的范围(分别位于派生类基类);(2)相同的函数名字;(3)参数相同(即参数类型参数个数均相同)...

web开发自学 121

reintroduceoverride overload有何区别,怎么使用?

reintroduceoverride overload有何区别,怎么使用?     在子孙类中要声明一个祖先类中参数不同的方法的时候用Reintroduce,     但需要重新定义一个祖先类总的虚拟的或者动态的方法的时候,要用到Override;如果祖先类中的方法不是虚拟的或者动态的(定义的时候有virtual;就是虚拟的,有dynamic;就是动态的);那么是没有办法override的     至于Overload,一般适用于定义一组不同参数的函数,这些函数也可以不是Of Objects(中文该怎

娃娃鸭的专栏 4696

重载覆盖

override   函数参数类型以及返回类型必须相同,即签名都是一致的——或者叫相貌衣服都是一样的,一般用在继承过程中。(高手判断一下,除了实现细节,其他的是不是什么都应该相同?所以叫做“重写”——《C++编程思想》上是这么翻译的。) overload   函数名必须相同,签名必须不同(参数个数,顺序,类型),返回类型可以不同,用在同一个类中,在编译时候确定。

小虾米就是我喽 417

DELPHIVC口水战”之补白

这里是原文:http://blog.csdn.net/jiangtao/archive/2001/03/05/1821.aspx  原文写得不错,不但引经据典,还罗列了十几条大多有统计数据的比较,不过,严格地说,DELPHI是一个IDE,它并不代表PASCAL这门语言,而VC也只是一个IDE,它并不代表C++,而MFC也不是它的全部,那么,把DELPHIVC相比,到底是比什么呢?  如果是比“用

于无声处 3344

171230—重载覆盖、隐藏

按:一入此门深似海…… 此篇仅是个人的一些理解。希望能把自己之前遇到的问题的思考后续研究整理出来。 此诸概念在面向对象的编程范围内讨论。重载:(overloaded)抄百度:重载,简单说,就是函数或者方法有相同的名称,但是参数列表不相同的情形,这样的同名不同参数的函数或者方法之间,互相称之为重载函数或者方法。也就是说,重载,是在同一个类中,多个函数共用一个函数名,但由于其参数的不同,各函数可以

DRondong的博客 327

浅析重载、隐藏覆盖

重载 重载又称为静态多态,静态绑定,静态决议等。因为要实现重载,所以C++C的命名方式有所不同。重载主要是为了减轻程序员对函数名的记忆负担,让所有功能相似的函数使用同一名字。 重载条件: (1)在同一作用域中 (2)函数名相同 (3)参数列表不同 隐藏 隐藏是因为在子类中定义了基类同名的函数

double_happiness的博客 827

delphi C++的基本语法区别

http://www.cnblogs.com/Braveliu/p/3602784.html 【1】“=”符号 (1)“=”作为比较符。但是,当定义const常量时,“=”又表示赋值符号。而“:=”作为赋值符号。 (2)“=”只表示赋值符号 【2】结构体 (1)record 作为结构体 (2)struct 作为结构体 【3】继承 (1)

ly930156123的博客 1084
下一篇: 在VC++中读写INI文件
lcj8
博客等级 码龄21年 166粉丝 669原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值