C++与C# 对函数隐藏的不同处理

看一段简单的C++代码

  1. #include <iostream>
  2. class A
  3. {
  4. public:
  5.     void f(float x)
  6.     {
  7.         std::cout << "A::f(float)" << std::endl;
  8.     }
  9.     void f(int x, int y)
  10.     {
  11.         std::cout << "A::f(int,int)" << std::endl;
  12.     }
  13. };
  14. class B : public A
  15. {
  16. public:
  17.     void f(int x)
  18.     {
  19.         std::cout << "B::f(int)" << std::endl;
  20.     }
  21. };
  22. int main(int argc, char * argv[])
  23. {
  24.     B b;
  25.     b.f(2.3);
  26.     // b.f(2,3); occur error
  27.     return 1;
  28. }

执行结果应该是什么呢?

记住这种情况不会实现函数重载的,因此调用b.f(2,3)会出现编译错误,而调用b.f(2.3)不会调用基类的f函数,而会调用派生类的f函数(参数类型隐性转换),函数隐藏的概念摘录如下

隐藏是指派生类的函数屏蔽了与其同名的基类函数,规则如下:

  1. 如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)
  2. 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)

再看同样代码的C#实现

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. namespace FunctionTest
  5. {
  6.     class Program
  7.     {
  8.         static void Main(string[] args)
  9.         {
  10.             B b = new B();
  11.             b.f(2.3f);
  12.             b.f(2, 3); // work well
  13.         }
  14.     }
  15.     public class A
  16.     {
  17.         public void f(int x)
  18.         {
  19.             Console.WriteLine("A::f(int)");
  20.         }
  21.         public void f(int x, int y)
  22.         {
  23.             Console.WriteLine("A::f(int,int)");
  24.         }
  25.     }
  26.     public class B : A
  27.     {
  28.         public void f(float x)
  29.         {
  30.             Console.WriteLine("B::f(float)");
  31.         }
  32.     }
  33. }

会发现与C++的不同之处,在C#中不会进行函数隐藏,即使派生类与基类同名,参数不同也能实现类似函数重载,执行结果是

A::f(float)

A::f(int,int)

这样的结果才会符合我们预期的设想,也许这也算是C++设计的一个不足之处吧

为了验证这真的算是函数重载么,把上面的程序简单改变一下,再看下面一段C#代码

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. namespace FunctionTest
  5. {
  6.     class Program
  7.     {
  8.         static void Main(string[] args)
  9.         {
  10.             B b = new B();
  11.             b.f(2);
  12.             b.f(2, 3); // work well
  13.         }
  14.     }
  15.     public class A
  16.     {
  17.         public void f(int x)
  18.         {
  19.             Console.WriteLine("A::f(int)");
  20.         }
  21.         public void f(int x, int y)
  22.         {
  23.             Console.WriteLine("A::f(int,int)");
  24.         }
  25.     }
  26.     public class B : A
  27.     {
  28.         public void f(float x)
  29.         {
  30.             Console.WriteLine("B::f(float)");
  31.         }
  32.     }
  33. }

 

执行结果是

B::f(float)

A::f(int,int)

此时为什么没有调用基类的函数呢 这与普通的函数重载肯定也有不同之处,我的理解是派生类中的函数会有比基类更高的优先级,int能直接转换为float型,然后进行调用,反之float转换成int,是不能隐式进行的,所以调用了基类的函数。这只是我的理解,如果有更好的解释情留言告诉我。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值