zoukankan      html  css  js  c++  java
  • 由ios学到的C++用户自定义转换

         与学长在群里讨论到了iostream的>>操作符的返回值问题,记得曾经找资料的时候有说过>>返回的是流引用,不过可以被转换成bool,因此可以被直接用在while中作为条件。当时就记得有这么回事,也没有继续深入;今天正好借此机会好好补一补,心得记录下来,备用。

         我翻看了vc6.0中的iostream及相关头文件,所有>>操作符的返回值都是basic_stream<>&(另外模板对char*和wchar_t*做了特别的定义),并没有返回bool型的;随后百度,发现了端倪:

    //<xiosbase> in VC6.0
            operator void *() const
                    {return (fail() ? 0 : (void *)this); }
            bool operator!() const
                    {return (fail()); }

         在vc6里上面的两个函数是在class ios_base中,位于文件XIOSBASE。不怕大家笑话,本菜从未见过operator void*这样的重载,甚是不解。我只看过一本C++的教程,是谭浩强先生的《C++程序设计》,还是第一版。那本书当时我大概完整地看了有三四遍,记得书中没有讲过有关用户自定义转换的东西,也很久没有再碰过那本书了,因为借给了同学……还是自己再找点东西吧。

         首先,>>操作符返回的是流引用,所以才可以实现连续>>的操作。>>和<<都是从左至右结合,就是说譬如cin>>a>>b;这样的语句,先结合cin>>a,输入a之后返回流引用(就相当于是cin),继续与后面的>>b结合,就相当于是cin>>b,再次输入b的值。

         其次,ios_base还重载了void*。这种重载相当于是定义了一种转换,由当前类型转换到重载中声明的类型。由其他类型转换至当前类型很简单,依靠构造函数就能解决;而从当前类型转换至其他类型就需要靠这种重载来转换,而且这种转换可以衔接到标准转换序列中。比如上述void*的转换,返回的是一个指针,指针的本质其实就相当于一个ULONG类型的变量,进而转换至bool类型。所以,不论是while(cin)还是while(cin>>a)这样的写法,都可以得到正确的结果。

         因此,用户自定义转换主要用于用户自定义类型与其他类型(既包括内置类型也包括自定义类型)之间的相互转换,可以分为两大部分:从其他类型到当前类型的转换;从当前类型到其他类型的转换。前者主要是利用构造函数实现,后者主要靠重载转换操作符来实现,而且重载函数没有参数也没有返回值。另外,这种转换之后的类型只允许进入标准转换序列。也就是说,如果在用户自定义转换之后仍需进行另一次用户自定义转换,编译器将不会进行隐式转换(也许我们用该要么勤快一点,多写一步显示转换;要么一步到位,再重载一个转换操作符)。不过这种重载也可能造成二义性,也分两种情况:

    1.类型转换序列中的二义性问题

         这种二义性在标准转换序列中就比较常见,比如float和int都可以经由标准序列转换为long(没有一个是精确匹配),此时就是二义的;这种情况当然可能出现在我们的用户自定义转换当中。

    2.两种用户自定义转换之间的矛盾

         假如有这样一个代码,class A中由构造函数提供了从B到A的隐式转换(通过构造函数);而在B中提供了由B到A的转换(通过重载转换操作符),那么在转换的时候到底应该应用哪一个呢?此问编译器不解,遂其罢工也……

         解决方法是这样的:一种方法为调用B.operator A()来显示调用(有人说用A(B)也能达到目的,可以成功编译。也许是C++标准和编译器实现不同所致?),另一种方法为用explicit关键字显示声明A的构造函数,这样A的构造函数将不再参与隐式转换,也就消除了此类转换的二义性。

  • 相关阅读:
    A2-02-15.DML-MySQL RIGHT JOIN
    A2-02-14.DML- MySQL LEFT JOIN
    A2-02-13.DML- MySQL INNER JOIN
    NHibernate N+1问题实例分析和优化
    怎么创建移动页面应用程序
    .NET开发时让人头痛的SESSION超时
    WCF服务编程——数据契约快速入门
    数据模型类对比,用反射做个快乐的程序员
    javascript常见数据集
    provider:命名管道提供程序,error:40
  • 原文地址:https://www.cnblogs.com/tuesday/p/2329277.html
Copyright © 2011-2022 走看看