首先声明,转载自:http://blog.csdn.net/skdkjzz/article/details/45872801

转换函数的名称是类型转换的目标类型,因此,不必再为它指定返回值类型;转换函数是被用于本类型的数值或变量转换为其他的类型,也不必带参数

在写这篇文章之前,让我们先回顾一下编译器通过匹配过程确定调用哪一个函数的匹配顺序:
(1)寻找和使用最符合函数名和参数类型(包括返回值)的函数,若找到则调用;

(2)否则,寻找一个函数模板,将其实例化产生一个匹配的重载函数,若找到则调用;

(3)否则,寻找可以通过类型转换进行参数匹配的重载函数,若找到则调用它。

如果以上步骤均未找到匹配函数,则这个调用是错误的;如果这个调用有多于一个的匹配选译,则调用匹配出现二义性,也是错误的。
  
类型转换是将一种类型的值映射为另一种类型的值。类型转换实际上包含有自动隐含和强制的两种。

C语言编译系统提供的内部数据类型的自动隐式转换规则如下:

1.程序在执行算术运算时,低类型可以转换为高类型。

2.在赋值表达式中,右边表达式的值自动隐式转换为左边变量的类型,并赋值给它。

3.当在函数调用时,将实参值赋给形参,系统隐式地将实参转换为形参的类型后,赋给形参。

4.函数有返回值时,系统将自动地将返回表达式类型转换为函数类型后,赋值给调用函数。

在以上情况下,系统会进行隐式转换的。当在程序中发现两个数据类型不相容时,又不能自动完成隐式转换,则将出现编译错误。例如:
   int* p = 100;
在这种情况下,编译程序将报错,为了消除错误,可以进行如下所示的强制类型转换:
   int* p = (int *)100; 
将整型数100显式地转换成指针类型。

构造函数具有类型转换功能

在实际应用中,当类定义中提供了单个参数的构造函数时,该类便提供了一种将其他数据类型的数值或变量转换为用户所定义数据类型的方法。因此,可以说单个参数的构造函数提供了数据转换的功能。下面通过一个例子进一步说明单参数构造函数的类型转换功能。

代码如下:

class A
{
public:A(){ m=0; } A(doublei) { m=i; } void print() { cout<<M<<endl}
private:double m;
};void main()
{A a(5); a=10; //a与10是不同的数据类型a.print();
}

程序的输出结果为:
  10
在该程序中,赋值语句a=10;中,赋值号两边数值10和对象a是两上不相容的数据类型,可是它却能顺利通过编译程序,并且输出显示正确结果,其主要原因是得益于单参数的构造函数。编译系统选通过标准数据类型转换,将整型数值10转换成double型,然后,再通过类中定义的单参数构造函数将double型数值转换为A类类型,最后把它赋值给a。这些转换都是自动隐式完成的。

关于上面的程序,补充一点:
Aa = 10; 

Aa; 
a= 10; 
两者是不同的,前者对a进行初使化,编译器会尝试将10隐式转换为A类型,这样将引起a的A(doublei)构造函数直接被调用。
后者属于赋值语句,编译器将建立一个临时对象,并将10隐式转换为A类型。如果我们显示调用
(A)10;
这也将建立一个临时对象,引起A的构造函数被调用。

还有一点要注意,编译器只会进行一次隐式转换(C时刻库的内置类型如intshort char等)除外,下面的语句说明了这点:
m_rst->GetFields()->GetItem(nCol)->Value= (_bstr_t)sValue; 
上面Value是COM的变体类型,“Value=”将引起operator= (_bstr_t)被调用。如果上面省略(_bstr_t),编译器将发生错误,因为没有operator= (char*)这样的重载,编译器不会为我们进行两次以上的隐式转换。

在函数调用过程中,运算符重载和构造也是一个函数调用,如果匹配的函数如无二义性,那么将可以产生一次隐式转换。如果上句的Value变体类只有一个operate= (_bstr_t),那么既使这样写->Value= sValue; 编译器也会试图将sValue隐式转换为_bstr_t类型。

还有一种情况

代码如下:

classA 
{
    int a; 
public:
    A(){ }; 
    A(int_a) { a = _a; }; 
    Operator int() { return a; } 
}

有如下调用:

代码如下:

A a(10); 
A a2 = (int)(int)a;   //只相当于Aa2 = (int)a; 因为第一个就近已经转成了int,第二//个就不用再转了

比较有意思吧,A类既有将int隐式转换A的构造,也有int()转换函数供强制转换,(int)(int)a将以就近原则的方式进行。如果就近转换失败,编译器将报错。比如:

代码如下:

classB 
{
};
A a2 = (B)a; 

A a2 = (B)10;

编译器报这样的错误:"errorC2440: “类型转换”:无法从“int”转换为“B”"
可知,我们自己编写的构造和转换函数多么重要。

转换函数
转换函数又称类型强制转换成员函数,它是类中的一个非静态成员函数。它的定义格式如下:

代码如下:

   class<类型说明符1>
    {
     public:
      operator<类型说明符2>();
      …
    }

这个转换函数定义了由<类型说明符1>到<类型说明符2>之间的映射关系。可见,转换函数是用来将一种类型的数据转换成为另一种类型。下面通过一个例子说明转换函数的功能。

代码如下:

#includeclass Rational
{
public:Rational(intd, int n) {den= d; num= n; }operator double();//类型转换函数
private:int den, num;
};Rational::operator double()
{return double(den)/double(num);
}void main()
{Rational r(5, 8); double d = 4.7; d += r;  //这句将调用隐式转换,相当于d= (double)r; cout<<d<<ENDL;
}

程序输出结果:
5.325

由程序可知,d是一个double型数值,r是Rational类的对象,这两个不同类型的数据进行加法之所以能够进行是得益于转换函数operatordouble()。为使上述加法能够进行,编译系统先检查类Rational的说明,看是否存在在下转换函数能够将Rational类型的操作数转换为double类型的操作数。由于Rational类中说明了转换函数operatordouble(),它可以在程序运行时进行上述类型转换,因此,该程序中实现了d=r;的操作。

定义转换函数时应注意如下几点:
(1)转换函数是用户定义的成员函数,但它要是非静态的。
(2)转换函数的不可以有返回值。(意思是声明中不可以有返回值)
(3)转换函数也不带任何参数。
(4)转换函数函数还不能定义为友元函数。

转换函数的名称是类型转换的目标类型,因此,不必再为它指定返回值类型;转换函数是被用于本类型的数值或变量转换为其他的类型,也不必带参数。

类中的构造函数完成其他类型到类类型的转换,而重载强制转换完成类类型到其他类型的转换。

1.  operator 用于类型转换函数:

类型转换函数的特征:

1)  型转换函数定义在源类中;
2)  须由 operator 修饰,函数名称是目标类型名或目标类名;
3)  函数没有参数,没有返回值,但是有return
语句,在return语句中返回目标类型数据或调用目标类的构造函数。

类型转换函数主要有两类:

1)  对象向基本数据类型转换:

对象向不同类的对象的转换:

例程1:

//通过类型转换函数求半径为5的圆的面积
//并将其存储在float型变量中打印输出
#include <iostream>
using namespace std;
class CArea
{float area;
public:CArea(){area=0;}CArea(float a)           //重载含有一个参数的构造函数{area=a;}void getArea(){cout<<area<<endl;}void setArea(float a){area=a;}operator float()            //类型转换函数{                              //将面积类对象转换为float型数据return area;}
};
class CCircle
{float R;
public:void getR(){cout<<R<<endl;}void setR(float r){R=r;}operator CArea()   //类型转换函数{                                 //将圆类对象转为面积类对象float area=3.1415926*R*R;return (CArea(area));}
};
void main()
{CCircle cir;CArea are;float a;cir.setR(5);cir.getR();                     //打印圆的半径are.getArea();           //打印转换前的面积                  are=cir;                 //将圆类对象转为面积类对象are.getArea();           //打印转换后的面积   a=are;                          //将面积类对象转换为float型数据cout<<a<<endl;
}    //将面积类对象转换为float型数据return area;}
};
class CCircle
{float R;
public:void getR(){cout<<R<<endl;}void setR(float r){R=r;}operator CArea()   //类型转换函数{                                 //将圆类对象转为面积类对象float area=3.1415926*R*R;return (CArea(area));}
};
void main()
{CCircle cir;CArea are;float a;cir.setR(5);cir.getR();                     //打印圆的半径are.getArea();           //打印转换前的面积                  are=cir;                 //将圆类对象转为面积类对象are.getArea();           //打印转换后的面积   a=are;                          //将面积类对象转换为float型数据cout<<a<<endl;
}

2.  operator 用于操作符重载:

操作符重载的概念:

将现有操作符与一个成员函数相关联,并将该操作符与其成员对象(操作数)一起使用。

注意事项:

1)  重载不能改变操作符的基本功能,以及该操作符的优先级顺序。

2)  重载不应改变操作符的本来含义。

3)  只能对已有的操作符进行重载,而不能重载新符号。

4)  操作符重载只对类可用。

5)  以下运算符不能被重载:

.       原点操作符(成员访问符)

*     指向成员的指针

::       作用域解析符

? :     问号条件运算符

sizeof 操作数的字节数

操作符函数的一般格式:

return_type operator op(argument list);

return_type:返回类型(要得到什么)

op:要重载的操作符

argument list:参数列表(操作数有哪些)

例程2:

//重载大于号操作符比较两个人的工资
#include <iostream>
using namespace std;
class employee
{int salary;
public:void setSalary(int s){salary=s;}void getSalary(){cout<<salary<<endl;}bool operator >(const employee & e)//重载大于号操作符{if(salary > e.salary)return true;elsereturn false;}
};
void main()
{employee emp1,emp2;emp1.setSalary(1000);emp2.setSalary(2000);if (emp1 > emp2){cout<<"emp1比emp2工资高"<<endl;}else{cout<<"emlp1没有emp2工资高"<<endl;}
}

声明:operator XX(); 无返回值,XX就是某个类型;

用法:XX a = (XX)obj; 假设上边SocketAddress非abstract类,例如:SocketAddress sa; int a = (socklen_t)sa; 也就是此时会调用原成员函数operator XX(); 一般返回XX类型值,可以理解成类型转换的重载!

另外:一个自定义类的 构造函数可以用作隐形的类型转换,

例如:Class A { A(int i) { val = i};  private int val;} , A a = 5;

解:5 首先通过构造函数A(int)隐形的转换为A类型,然后调用默认的operator=赋值函数,赋值给a;

C++中operator的两种用法相关推荐

  1. operator的两种用法

    C++ operator两种用法 C++中的operator,有两种用法,一种是operator overloading(操作符重载),一种是operator casting(操作隐式转换).下面分别 ...

  2. jsp中include 的两种用法

    1.两种用法 静态include: <%@ inlcude file ="header.jsp" %> 此时引入的是静态的jsp文件,它将引入的jsp中的源代码原封不动 ...

  3. vue3.0中setup使用(两种用法)

    这篇文章主要介绍了vue3.0中setup使用,本文通过两种用法给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下 一.setup函数的特性以及作用 可以确定的是 V ...

  4. jsp中include的两种用法

    1.两种用法 第一种:include指令:通过file属性来指定被包含的页面,当JSP转换成Servlet时引入指定文件,一般不需要写头 <%@ pagecontentType="te ...

  5. java中super_java中super的两种用法

    转自:http://blog.csdn.net/yihuei123/archive/2007/06/04/1637893.aspx 通过用static来定义方法或成员,为我们编程提供了某种便利,从某种 ...

  6. (转载)java中super的两种用法

    (转载)http://www.cnblogs.com/rollenholt/articles/2033989.html 通过用static来定义方法或成员,为我们编程提供了某种便利,从某种程度上可以说 ...

  7. Java中return的两种用法

    一.return语句总是用在方法中,有两个作用. 一个是返回方法指定类型的值(这个值总是确定的). 一个是结束方法的执行(仅仅一个return语句). 一般的就百是用在有反回值的方法中,用来返回方度法 ...

  8. js高级编程中命名空间的两种用法

    第一种: // 声明一个全局对象Namespace,用来注册命名空间 Namespace = new Object(); // 全局对象仅仅存在register函数,参数为名称空间全路径,如" ...

  9. jsp中include的两个用法

    我们都知道在jsp中include有两种情势,分别是 <%@ include file=" "%> <jsp:include page=" " ...

最新文章

  1. django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.3
  2. 高性能服务器架构(一):缓冲策略
  3. window系统快捷键
  4. poj2586(贪心盈亏问题)
  5. nhibernate3 linq的的select 操作
  6. 公共计算机课程思政建设实施方案,公共计算机教研组开设课程思政公开课
  7. 使用临界段实现优化的进程间同步对象-原理和实现
  8. 使用yield返回IEnumberT集合
  9. 《Tensorflow 实战》(完整版,附源码)
  10. 解决应用程序无法正常启动0xc0150002问题(转)
  11. 一分钟教会你黑白图片如何上色
  12. python封装exe后其他人能用么_python用tesseract写的图片识别,封装exe后,本机可以用,软件放别的电脑上无法图......
  13. Qt -设计嵌入式设备用户界面的利器
  14. 用c语言表现一元多项式的除法,c语言编程实例一元多项式的计算
  15. Halting Problem的讨论
  16. 【Matlab】如何规范地编写一个MATLAB函数文件
  17. 视频教程-2019 react入门至高阶实战,含react hooks-ReactJS
  18. 脑裂问题以及如何避免
  19. 【肆】财务自由的三大核心工具
  20. P1914 小书童——凯撒密码

热门文章

  1. php框架laravel百科,PHP 的Laravel 框架
  2. 知识图谱入门视频(三)
  3. 召回粗排精排-级联漏斗(下)
  4. Facebook提出生成式实体链接、文档检索,大幅刷新SOTA!
  5. Sigmoid函数与Softmax函数的区别与联系
  6. 从逻辑回归到神经网络
  7. 美团外卖客户端高可用建设体系
  8. pip加速+百度镜像|清华镜像
  9. Tensorflow实现LSTM详解
  10. 情报领域因果推理智能项目概览:以DAPAR为例