📅  最后修改于: 2020-03-24 01:11:09             🧑  作者: Mango
如果我们在基类中有一个函数,而在派生类中有一个同名函数,那么可以从派生类对象中调用基类函数吗?这是一个有趣的问题,作为实验可以预测以下C++程序的输出。
#include
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(double): 6.3
f(double): 6.6
而不是假定的输出:
f(int): 6
f(double): 6.6
重载不适用于C++编程语言中的派生类。基类和派生类之间没有重载定义。编译器查看派生类的范围,找到单个函数“ double f(double)”并调用它。它永远不会干扰基类的(封装)范围。在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 (int): 6
f (double): 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(double) : 6.3
f(double): 6.6
而不是假设的输出
f(int) : 6
f(double) : 6.6
原因与C++程序中说明的相同。像C++一样,在基类和派生类之间没有重载解析。在C#中,没有作用域之间的重载,派生类作用域也不是该一般规则的例外。这与C++相同,因为C#语言的创建者Anders hejlsberg认为,C#的设计与C++更加接近。