C/C++编程笔记:重载可以与继承一起使用吗?

126 阅读4分钟

如果我们在基类中有一个函数,而在派生类中有一个同名函数,那么可以从派生类对象中调用基类函数吗?这是一个有趣的问题,作为实验可以预测以下**C ++**程序的输出。

#include <iostream>using namespace std;class Base{public:int f(int i){cout << "f(int): ";return i+3;}};class Derived : public Base{public:double f(double d){cout << "f(double): ";return d+3.3;}};int main(){Derived* dp = new Derived;cout << dp->f(3) << '\n';cout << dp->f(3.3) << '\n';delete dp;return 0;}

该程序的输出为:

f(双精度):6.3

f(双精度):6.6

而不是假定的输出:

f(整数):6

f(双精度):6.6

重载不适用于C ++编程语言中的派生类。Base和Derived之间没有重载分辨率。编译器查看Derived的范围,找到单个函数“ double f(double)”并调用它。它永远不会干扰Base的(封闭)范围。在C ++中,没有作用域之间的重载-派生类作用域不是该一般规则的例外。

现在考虑该程序的Java版本:

class Base{public int f(int i){System.out.print("f (int): ");return i+3;}}class Derived extends Base{public double f(double i){System.out.print("f (double) : ");return i + 3.3;}}class myprogram3{public static void main(String args[]){Derived obj = new Derived();System.out.println(obj.f(3));System.out.println(obj.f(3.3));}}

上面程序的输出是:

f(整数):6

f(双精度):6.6

因此,在Java中,重载可在与C ++相反的范围内进行。Java编译器根据用于调用方法的参数类型来确定要在编译时执行的重载方法的正确版本,这两个类的重载方法的参数都会接收在调用中使用的参数的值并执行重载方法。

最后,让我们尝试以下**C#**程序的输出:

using System;class Base{public int f(int i){Console.Write("f (int): ");return i + 3;}}class Derived : Base{public double f(double i){Console.Write("f (double) : ");return i+3.3;}}class MyProgram{static void Main(string[] args){Derived obj = new Derived();Console.WriteLine(obj.f(3));Console.WriteLine(obj.f(3.3));Console.ReadKey(); // write this line if you use visual studio}}

注意:Console.ReadKey()用于暂停控制台。它类似于C / C ++中的getch。

上面程序的输出是:

f(双精度):6.3

f(双精度):6.6

代替假设的输出

f(整数):6

f(双精度):6.6

**说明:**在这里,我们正在创建派生类的对象,因此编译器将优先考虑派生类,并在需要时执行隐式类型转换。因此,一旦编译器到达_Console.WriteLine(obj.f(3));_ 这行代码将检查参数兼容性。在这里,图3是_INT_其与兼容_双_的_派生类函数f_。因此,编译器将执行_int到double_的隐式类型转换。因此,输出_f(double):6.3_将会出现。

现在,当编译器运行在_Console.WriteLine(obj.f(3.3));处。,它将再次赋予派生类优先级,并发现可调用。因此它将评估派生类函数_f。因此,输出_f(double):6.6_将会出现。

现在让我们再来看一次将基类函数f放入派生类中的情况,反之亦然,如下所示:

using System;class Base{public double f(double i){Console.Write("f (double) : ");return i+3.3;}}class Derived : Base{public int f(int i){Console.Write("f (int): ");return i + 3;}}class MyProgram{static void Main(string[] args){Derived obj = new Derived();Console.WriteLine(obj.f(3));Console.WriteLine(obj.f(3.3));Console.ReadKey(); // write this line if you use visual studio}}

输出:

f(整数):6

f(双精度):6.6

您对预期的输出感到震惊吗?这怎么可能?

好吧,我们对这些问题有一个答案。由于我们已经创建了Derived类的对象,因此C#编译器将优先考虑derived,如果找不到任何兼容性,则将其用于基类。因此,当编译器位于_Console.WriteLine(obj.f(3))时;的代码行,它将检查_派生的类方法f,并发现可调用的,因此执行此方法,并输出_f(int):6_。现在当_Console.WriteLine(obj.f(3.3));_ 这行代码将执行,将发现派生的类方法不适合作为3.3(double)

与int数据类型不兼容,因此编译器现在将更喜欢基类,并且在那里找到最佳匹配并执行该匹配。因此,该输出为_f(双精度):6.6_。

原因与C ++程序中说明的相同。像C ++一样,在Base类和Derived类之间没有重载解析。在C#中,没有作用域之间的重载,派生类作用域也不是该一般规则的例外。这与C ++相同,因为C#语言的创建者Anders hejlsberg认为,C#的设计与C ++更加接近。

以上就是今天的全部内容了。每日分享小知识,希望对你有帮助~

**另外如果你想更好的提升你的编程能力,学好C语言C++编程!**弯道超车,快人一步!笔者这里或许可以帮到你~

C语言C++编程学习交流圈子,**QQ群【951258402】**微信公众号:C语言编程学习基地

分享(源码、项目实战视频、项目笔记,基础入门教程)

欢迎转行和学习编程的伙伴,利用更多的资料学习成长比自己琢磨更快哦!

编程学习视频分享: