C# 类型运算符重载在类继承中的调用测试

这是一篇晦涩难懂的片面的研究

一,简单的继承层次

    class CA {}class CB : CA{}class CC : CB{}}void Test(CA oa){//CATestDebug.Log ("CA===============");}void Test(CB oa){//CBTestDebug.Log ("CB===============");}void Test(CC oa){//CCTestDebug.Log ("CC===============");}//测试代码如下:CC oc = new CC ();Test (oc);    

在这种情形下调用Test(oc)有如下规律:<通过注释掉其它函数进行测试>

  1. 若CATest , CBTest, CCTest三个重载函数都存在,则Test(oc)将调用CCTest
  2. 若只有CATest, CBTest二个重载函数,则Test(oc)将调用CBTest
  3. 若三个函数只有一个存在,则Test(oc)即调用该函数。

由此我们得知,Test(oc)调用时,编译器会由oc的继承层次由子到父的优先级去匹配重载函数的形参。这也符合正常逻辑。

二,类中有运算符重载的继承

   class CA {}class CB : CA{}class CC : CB{
/*        MSDN类型转换的要求1.操作数必须是封闭类型2.类A到类B的类型转换定义不能在类C中进行(即2个类的转换不能在第3个类中定义, 如下面的参数定义)*/public static implicit operator bool(CC ot/*不能是CA ot或 CB ot */){Debug.Log ("bool================");return ot != null;}}void Test(CA oa){//CATestDebug.Log ("CA===============");}void Test(CB oa){//CBTestDebug.Log ("CB===============");}void Test(CC oa){//CCTestDebug.Log ("CC===============");}
   void Test(bool b){//boolTest     Debug.Log ("b===============")   }//测试代码如下:CC oc = new CC ();Test (oc);    

此情形下boolTest重载函数和CATest, CBTest, CCTest的任何一个重载都冲突,原因如下:

当调用Test(oc)时,编译系统将oc与Test的四个重载函数的参数进行匹配,却发现四个都能匹配成功。Test(bool b)通过CC类的bool类型符重载而匹配。

CATest, CBTest, CCTest三个重载函数由于形参CC,CB,CA是继承关系,在进行匹配时是有优先级的,由于ot是CC类型的,所以优先级CC>CB>CA,因此这个三个重载函数间没有冲突,编译器明确知道该调用哪个重载。而bool重载与CC,CB,CA在类型转换时是同优先级,因此编译系统不知道该调用bool重载还是CC,CB,CA的三个重载了。

若将bool重载由类CC移到类CA中,其它代码不变,测试代码不变。经测试,boolTest,CATest, CBTest, CCTest四个重载可以共存,即boolTest与其它任何一个重载都不冲突。

  1. boolTest,CATest, CBTest, CCTest同时存在,Test(oc)调用了CCTest
  2. boolTest,CATest, CBTest同时存在,Test(oc)调用了CBTest
  3. boolTest, CATest同时存在,Test(oc)调用了CATest
  4. boolTest,CATest, CBTest, CCTest只有一个存在,则调用此存在
  5. 只有boolTest存在时,该重载函数也被调用

这说明了基类的类型重载运算符的调用优先级低于父子层级转换的优先级,如情形5,在只有bool重载运算符时才会被调用。

本类的类型重载运算符的优先级等于父子层次转换的优先级。

三,Unity中的调用

UnityEngine所有类的的基类都是UnityEngine.Object。这个类与System.Object的关系很诡异。

System.Object obj = new UnityEngine.Object() //这行代码在编译上没问题,其实非常诡异,后面单独说

这样写可以正常编译。反过来将System.Object赋予UnityEngine.Object则不能编译通过。

这似乎可以说 System.Object 是 UnityEngine.Object的基类,网上许多人也这么认为。还有人说是隐式继承。

然而,通过看U3D的API,可以看到UnityEngine.Object并没有继承任何类,UnityEngine的源码中Object也确实没有继承任何类。这只能说是CLR内部自己的搞的鬼。

于是在这种情形下,重载函数的调用规律就有了一点小的改变。

这就是:UnityEngine.Object类及子类适用于上面的规律。而System.Object则处于所有类型的最低优先级,低于bool类型转换重载。例:

public class NewBehaviourScript : MonoBehaviour {void OTest(bool b){//F1
        Debug.Log ("OTest--b-");}void OTest(System.Object obj){//F2
        Debug.Log ("OTest-system-obj-");}void OTest(UnityEngine.Object obj)//F3
    {Debug.Log ("OTest-obj");}void OTest(Transform tran){//F4Debug.Log ("OTest-trans-");}void Start (){OTest (gameObject.transform);}void Update () {}
}

调用优先级F4>F3>F1>F2。即:

  1. F1,F2,F3,F4共存时,OTest (gameObject.transform)调用F4,因F4形参为Transfrom类型,与实参相同,接近度最高。
  2. 若仅有F1,F2,F3共存,OTest (gameObject.transform)调用F3,因F3形参为UnityEngine.Object类型,是实参类型Transfrom的直接父类,接近度最高。
  3. 若仅F1,F2共存,因System.Object只是UnityEngine.Object的隐式父类,在语法上已不是其父类了,这时编译器会试着寻找bool类型重载,结果找到了。
  4. 若仅F2存在,编译器既没找到可用的直接转换,也没找到bool重载,于是就剩下隐匿父类可以尝试了,于是调用F2。

当仅有F1,F2共存时,大多数人的直觉是:OTest (gameObject.transform)肯定会调用F2: OTest(System.Object obj),网上有些同学很早发现了这个诡异现象

附:System.Object obj = new UnityEngine.Object() 这个诡异问题。

  1. new 一个UnityEngine.Object的对象是不合语义的,可以看到Unity API中的描述:Instatiating a GameObject adds it to the scene so it's completely initialized (!destroyed). Instantiating a simple UnityEngine.Object has no such semantics, so the it stays in the 'destroyed' state which compares true to null
  2. UnityEngine.Object obj = new UnityEngine.Object() //null 这行代码的结果是obj为null,如1中所述。然而 
  3. System.Object obj = new UnityEngine.Object() //诡异在这里,调试数据如下

可以看到suo 与 uo的调试数据都是 {null},这大概就是表示对象为空吧,if(uo==null)成立,输出了 uo==null字符串,然而if(suo==null)却不成立!!对于神奇的.NET,我只能说:用unity时就别用system.Object了。

posted on 2016-10-06 18:34 时空观察者9号 阅读(...) 评论(...) 编辑 收藏

C# 类型运算符重载在类继承中的调用测试相关推荐

  1. 运算符重载为类的友元函数

    运算符重载为类的友元函数 友元函数通过类的对象可以访问类的公有.保护和私有成员,也就是类的所有成员友元函数都能访问到.所以运算符重载为类的友元函数以后也可以访问类的所有成员. 与运算符重载为成员函数时 ...

  2. 运算符重载为类的成员函数

    运算符重载 运算符重载为类的成员函数后就可以像其他成员函数一样访问本类的数据成员了. 在类的外部通过类的对象,可以像原运算符的使用方式那样使用重载的运算符,比如,"+"运算符被重载 ...

  3. C++运算符重载(类内、外重载)

    1.概念   运算符的重载,实际是一种特殊的函数重载,必须定义一个函数,并告诉C++编译器,当遇到该运算符时就调用此函数来行使运算符功能.这个函数叫做运算符重载函数(常为类的成员函数).   用函数的 ...

  4. C++:运算符重载与类的赋值运算符重载函数

    目录 章节知识架构 一.运算符重载 1. 运算符重载的基本概念 代码段1 2.关于运算符重载的重要语法细则 二.运算符重载在类中的使用 三.类的默认成员函数:=重载函数(赋值运算符重载) 1.自定义= ...

  5. 27、Python 面向对象(创建类、创建实例对象、访问属性、内置类属性、对象销毁、类的继承、方法重写、基础重载方法、运算符重载、类属性与方法、下划线双下划线)

    27Python面向对象(Python2) Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的.本章节我们将详细介绍Python的面向对象编程. ...

  6. C++编程入门--运算符重载复数类

    题目:成运算符重载员函数形式实现复数类的四则运算 上机指导2中,我们以独立函数形式(非成员函数,非友元函数)实现了Complex附属类的加减乘除四则运算,这里要求用Complex成员函数形式实现Com ...

  7. C++知识点45——类继承中的类型转换与访问权限控制(上)

    一.类的继承与类型转换 1.概述 一般情况,如果想把一个类的指针或引用绑定到另外一个对象上,需要指针或者引用的类型与指向对象一致.但是存在继承关系的类是个例外:可以将基类的指针或者引用指向子类 原因是 ...

  8. C语言中能运算符重载吗,C++语言中什么运算符不能重载

    2016-09-01 回答 c语言没有重载的概念,重载是c++的内容 c++运算符: 算术运算符:+,-,*,/,%,++,--; 位操作运算符:&,|,~,^(位异或),<<(左 ...

  9. php继承和重载区别,php继承中方法重载(覆盖)的应用场合

    php继承中方法重载(覆盖)的应用场合 发布于 2015-02-23 17:57:23 | 91 次阅读 | 评论: 0 | 来源: 网友投递 PHP开源脚本语言PHP(外文名: Hypertext ...

最新文章

  1. zabbix 安装_zabbix系列(五) Grafana4.6.3+Zabbix 的安装部署
  2. 酷桌面:随身携带你的企业
  3. 01-05 Linux常用命令-性能统计
  4. 低温linux内核启动readl,Linux内核启动流程分析(一)
  5. 宏碁 Aspire E1-471g黑苹果efi引导文件
  6. 02 CODESYS应用基础之ST语言语法基础
  7. 统计分析之:正态性检验——SPSS操作指南
  8. 逃脱只会部署集群系列 —— jenkins和gitlab的部署联动推送
  9. 使用GDI/GDI+绘制到D3D9缓冲区的方法
  10. 好用到爆!IDEA 版 Postman 面世了,功能真心强大
  11. 数组名 和数组名的理解
  12. Btree 数据结构
  13. 班主任工作总结 初中物资管理工作总结
  14. npm install时cb() never called!错误解决方法
  15. [apidoc]Apidoc-文档生成工具
  16. 2019全国高校深度学习师资培训班免费报名中
  17. java border类_Swing BorderLayout类
  18. bzoj 1902: Zju2116 Christopher lucas定理 数位DP
  19. NYoj88 汉诺塔(一)
  20. 读书笔记 - 人性的弱点 Chapter-3 如何让他人信服你

热门文章

  1. Leaflet中使用layerGroup图层组实现图层切换
  2. Navicat中怎样将SQLServer的表复制到MySql中
  3. Ubuntu Server 16.04 LTS上使用Docker部署Tomcat修改为80端口
  4. SSM-查询数据库获取下拉框的值并作为查询的筛选条件
  5. no such file or directory AndroidManifest.xml
  6. Tkinter的Menubutton组件
  7. 敏捷有效执行的关键软技能
  8. 直播预告丨行业大咖带你找到游戏企业经营新升级的正确打开方式
  9. 直播回顾 | 数据驱动「产品迭代」的三大场景详解
  10. 硅谷增长专家 Ian Thiel 来华,首次揭秘数据驱动增长的道与术