5.3 类型转换

5.3.1 系统预定义类型间的转换
1. 隐式转换:
例如: int x=5,y;
             y=3.5+x; //系统会自动先将int型的5转换为double型的5.0,在和3.5进行加法运算。
隐式类型转换的主要规则:
a.在赋值表达式A=B的情况下,赋值运算符右端B的值需要转换为A的类型后进行赋值。
b.当char或short类型变量与int类型变量进行运算时,将char或short类型转换为int类型。
c.当两个操作对象类型不一致时,在算术运算前,级别低的类型自动转换为级别高的类型。

2.显示转换:
在C语言中:(类型名)表达式 例如:(int)3.2------>结果就是3
在C++中: 类型名(表达式)       例如:int 3.2 ------>结果也是3
-------------------------------------------------------------------------------------------
5.3.2 类类型与系统预定义类型间的转换
方法:(1)通过转换构造函数进行类型转换
            (2)通过类型转化函数进行类型转换

1. 转换构造函数
转换构造函数也是构造函数的一种,它具有类型转换的作用,它的作用是将一个其他类型的数据转化成它所在类的对象。转换构造函数只有一个形参,用户可以根据需要定义转换构造函数,载寒暑类体中告诉编译系统如何进行类型转换。

例如 Complex com2(7.7); //将double类型的7.7转换为名字为com2的Complex类对象
Complex(7.7);                //将double类型的7.7转换为无名的一个临时的Complex类对象

通常,使用转换构造函数将一个指定的数据转换为类的对象方法如下:
(1)先声明一个类(例如Complex)

(2)在这个类中定义一个只有一个参数,参数是待转换类型的数据,在函数体中指定转换的类型。
例如:
Complex(double r) //函数体中转换构造函数
{real=r;imag=0;}

(3)可以用以下形式进行类型换
类名(待转换类型的数据) 例如:Complex(7.7)
这时,C++系统就自动调用转换构造函数,将double类型的7.7转换为Complex类型的无名临时对象,
其值为:
临时对象.real=7.7
临时对象.imag=0
//例5.15 转换构造函数

#include<iostream.h>
using namespace std;
class Complex{
public:
Complex(){}; //不带参数的构造函数
Complex(double r,double i) //带两个参数的构造函数
{
real = r;
imag = i;
}
Complex(double r) //转换构造函数
{
real = r;
imag = ;
}
friend Complex operator+(Complex &a,Complex &b) //定义友元运算符+重载函数
{
Complex temp;
temp.real= a.real+b.real;
temp.imag= a.imag+b.imag;
return temp;
}
void print();
private:
double real;
double imag;
};
void Complex::print()
{
cout<<real;
if(imag>) cout<<"+";
if(imag!=) cout<<imag<<"i\n";
}
int main()
{
Complex com1(1.1,2.2),com3,total1,total2;
Complex com2(7.7); //调用转换构造函数,将7.7转换成为对象com2
total1 = com1+com2; //两个Complex对象相加
total1.print(); com3 = Complex(7.7);
total2 = com1+com3;
total2.print(); return ;
} /*
说明:(1)转换构造函数也也是一种构造函数,它遵循构造函数的一般规则。转换构造函数
只有一个参数,作用是将一个其它类型的数据转换为它所在类的对象。但是,有
一个参数的不一定是转换构造函数,它也可以是普通的构造函数,仅仅是起对象
初始化的作用。
(2)转换构造函数不仅可以将一个系统预定义的标准类型数据转换成类的对象,也有
可以将另一个类的对象转换为构造函数所在的类对象。 如:可以将一个学生类对象转换为教师类对象,可以在Teacher类中写出下面的
转换构造函数:
Teacher(Student& s){ num=s.num;strcpy(name, s.name);sex=s.sex; }
但应注意,对象s中的num,name,sex必须是公用成员,否则不能被类外引用。
*/

2.类型转换函数
通过转换构造函数可以将一个指定的类型的数据转换为类的对象。但是不能将一个类的对象转换为其他的类型的数据,例如不能将一个Complex类的对象转换为double类型的数据。为此,C++提供了一个称为类型转换函数来解决这个转换问题。类型转换函数的作用是将一个类的对象转换为另一个类型的数据。

格式为:
operator 目标类型()
{
     函数体
}

其中,目标类型为希望转换成的类型,它既可以是预定义的标准数据类型也可以是其他类的类型。类型转换函数的函数名为"operator 目标类型",在函数名前面不能指定函数类型,也不能有参数。

通常,其函数体的最后一条语句是return语句,返回值的类型是该函数的目标类型。例如,已经声明一个类Complex,可以在Complex类中定义一个类型转换函数:

operator double()
{
      return real;
}
这个类型转换函数函数名是"operator double",希望转换成的目标类型是double,函数体为return real。这个类型转换的作用是:将一个Complex类对象转换为一个double类型的数据,其值是Complex类中的数据成员real的值。

//例5.16 类型转换函数的应用1

#include<iostream>
using namespace std;
class Complex{
public:
Complex(double r,double i)
{
real = r;
imag = i;
}
operator double() //类型转换函数
{
return real; //将Complex类的对象转换为一个double类型的数据
}
private:
double real;
double imag;
};
int main()
{
Complex com(2.2,4.4);
cout<<"Complex类的对象转换为一个double类型的数据:";
cout<<double(com)<<endl; //调用类型转化函数,将转换后的double类型的数据显示出来 return ;
}
/*
类型转换函数注意事项:
(1)类型转换函数只能定义为一个类的成员函数,而不能定义为友元函数。类型转化函数也可以
在类体中生命函数原型,而将函数体定义在类的外部。
(2)类型转换函数既没有参数,也不能在函数名前面指定函数类型。
(3)类型函数中必须有return语句,即必须送回目标类型的数据作为函数的返回值。
(4)一个类可以定义多个类型转换函数。C++编译器将根据类型转换函数名自动地选择一个合适的
类型转换函数予以调用。
*/

//例5.17 类型转换函数的应用2

#include<iostream>
using namespace std;
class Complex{
public:
Complex(double r,double i)
{
real = r;
imag = i;
}
operator double() //类型转换函数,将Complex的对象转换为一个double类型的数据
{
return real;
}
operator int()
{
return int(real); //类型转换函数,将Complex的对象转换为一个int类型的数据
}
private:
double real;
double imag;
};
int main()
{
Complex com1(22.2,4.4);
cout<<"Complex的对象转换为一个double类型的数据:";
cout<<double(com1)<<endl;//调用类型转换函数 Complex com2(66.6,4.4);
cout<<"Complex的对象转换为一个int类型的数据:";
cout<<int(com2)<<endl; //调用类型转换函数 return ;
}
/*
运行结果:
Complex的对象转换为一个double类型的数据:22.2
Complex的对象转换为一个int类型的数据:66
*/

//[例10.10] 包含转换构造函数、运算符重载函数和类型转换函数的程序

#include <iostream>
using namespace std;
class Complex
{
public:
Complex( ){real=;imag=;} //默认构造函数
Complex(double r){real=r;imag=;}//转换构造函数
Complex(double r,double i){real=r;imag=i;}//实现初始化的构造函数
friend Complex operator + (Complex c1,Complex c2); //重载运算符“+”的友元函数
void display( );
private:
double real;
double imag;
};
Complex operator + (Complex c1,Complex c2)//定义运算符“+”重载函数
{
return Complex(c1.real+c2.real, c1.imag+c2.imag);
}
void Complex::display( )
{
cout<<"("<<real<<","<<imag<<"i)"<<endl;
}
int main( )
{
Complex c1(,),c2(,-),c3;
c3=c1+2.5; //复数与double数据相加,程序中不必显式地调用类型转换函数,它是自动被调用的,即隐式调用
c3.display( );//c1+2.5----->c1+Complex(2.5)
return ;
}

注意,在Visual C++ 6.0环境下运行时,需将第一行改为#include <iostream.h>,并删去第2行,否则编译不能通过。
对程序的分析:
1) 如果没有定义转换构造函数,则此程序编译出错。

2) 现在,在类Complex中定义了转换构造函数,并具体规定了怎样构成一个复数。由于已重载了算符“+”,在处理表达式c1+2.5时,编译系统把它解释为 operator+(c1, 2.5),由于2.5不是Complex类对象,系统先调用转换构造函数Complex(2.5),建立一个临时的Complex类对象,其值为(2.5+0i)。上面的函数调用相当于 operator+(c1, Complex(2.5)),将c1与(2.5+0i) 相加,赋给c3。运行结果为 (5.5+4i)

3) 如果把“c3=c1+2.5;”改为c3=2.5+c1; 程序可以通过编译和正常运行。过程与前相同。

从中得到一个重要结论,在已定义了相应的转换构造函数情况下,将运算符“+”函数重载为友元函数,在进行两个复数相加时,可以用交换律。如果运算符函数重载为成员函数,它的第一个参数必须是本类的对象。当第一个操作数不是类对象时

,不能将运算符函数重载为成员函数。如果将运算符“+”函数重载为类的成员函数,交换律不适用。由于这个原因,一般情况下将双目运算符函数重载为友元函数。单目运算符则多重载为成员函数。

4) 如果一定要将运算符函数重载为成员函数,而第一个操作数又不是类对象时,只有一个办法能够解决,再重载一个运算符“+”函数,其第一个参数为double型。当然此函数只能是友元函数,函数原型为 friend operator+(double, Complex &);显然这样做不太方便,还是将双目运算符函数重载为友元函数方便些。

5) 在上面程序的基础上增加类型转换函数:
operator double( ){return real;}
此时Complex类的公用部分为:
public:
Complex( ){real=0;imag=0;}
Complex(double r){real=r;imag=0;}         //转换构造函数
Complex(double r,double i){real=r;imag=i;}
operator double( ){return real;}                //类型转换函数
friend Complex operator+ (Complex c1,Complex c2); //重载运算符“+”
void display( );
其余部分不变。程序在编译时出错,原因是出现二义性。

C++:类型转换的更多相关文章

  1. 为C# as 类型转换及Assembly.LoadFrom埋坑!

    背景: 不久前,我发布了一个调试工具:发布:.NET开发人员必备的可视化调试工具(你值的拥有) 效果是这样的: 之后,有小部分用户反映,工具用不了(没反应或有异常)~~~ 然后,建议小部分用户换个电脑 ...

  2. c# 基础 object ,new操作符,类型转换

    参考页面: http://www.yuanjiaocheng.net/webapi/config-webapi.html http://www.yuanjiaocheng.net/webapi/web ...

  3. Struts2日期类型转换

    针对日期类java.util.Date进行类型转换,要求客户端使用"yyyy-MM-dd","yyyy/MM/dd"中的任意一种输入,并以"yyyy- ...

  4. 【.NET深呼吸】基础:自定义类型转换

    照例,老周在开始吹牛之前,先讲讲小故事,这是朋友提出的建议,老TMD写技术有什么了不起的,人人都会写.后来老周想想,也确实,代码谁不会写,能写到有品位有感悟,就不容易做到.于是,老周接受了该朋友的建议 ...

  5. C++四种类型转换方式。

    类型转换有c风格的,当然还有c++风格的.c风格的转换的格式很简单(TYPE)EXPRESSION,但是c风格的类型转换有不少的缺点,有的时候用c风格的转换是不合适的,因为它可以在任意类型之间转换,比 ...

  6. struts2类型转换

    1. Struts2中的类型转换 我们知道通过HTTP提交到后台的数据,都是字符串的形式,而我们需要的数据类型当然不只字符串类型一种.所以,我们需要类型转换! 在Struts2中,类型转换的概念除了用 ...

  7. C++_系列自学课程_第_11_课_类型转换_《C++ Primer 第四版》

    上次说了关于表达式的一些内容,说到还有一些关于数据类型转换的内容,今天我们接着八一八C++中的数据类型转换. 一.隐式类型转换 在表达式中,有些操作符可以对多种类型的操作数进行操作, 例如 + 操作符 ...

  8. Struts2入门(三)——数据类型转换

    一.前言 笔者一直觉得,学习一个知识点,你首先要明白,这东西是什么?有什么用?这样你才能了解.好了,不说废话. 1.1.类型转换为何存在?什么是类型转换? 在MVC框架中,都是属于表示层解决方案,都需 ...

  9. js条件判断时隐式类型转换

    Javascript 中,数字 0 为假,非0 均为真 在条件判断运算 == 中的转换规则是这样的: 如果比较的两者中有布尔值(Boolean),会把 Boolean 先转换为对应的 Number,即 ...

  10. JavaScript中数据类型转换总结

    JavaScript中数据类型转换总结 在js中,数据类型转换分为显式数据类型转换和隐式数据类型转换. 1, 显式数据类型转换 a:转数字: 1)Number转换: 代码: var a = " ...

随机推荐

  1. Python脚本控制的WebDriver 常用操作 <十九> 获取测试对象的状态

    下面将使用webdriver来模拟测试中观察测试对象的状态的操作 测试用例场景 在web自动化测试中,我们需要获取测试对象的四种状态 是否显示.使用element.is_displayed()方法: ...

  2. 【译】Android系统简介—— Activity

    续上一篇,继续介绍Android系统.上一篇: [译]Android系统简介 本文主要介绍构建Android应用的一些主要概念: Activity Activity是应用程序中一个单独的有UI的页面( ...

  3. js中typeof可以准确判断哪些变量类型

    typeof 运算符返回一个用来表示表达式的数据类型的字符串.  可能的字符串有:"number"."string"."boolean".& ...

  4. Android 中的WiFi剖析

    Android的WiFi 我们通常看到WiFi的守护进程wpa_supplicant在我们的ps的进程列表中,这个就是我们的wifi守护进程.wpa_supplicant在external/wpa_s ...

  5. mysql5.5 Replication 主从同步

    mysql5.5 Replication 主从同步 ------------------[主]------------------[mysqld]server-id=1 log-bin=mysql-b ...

  6. Unity3D实现立体迷宫寻宝

    Unity3D实现立体迷宫寻宝 这个小游戏是一个白痴在一个昏暗的房间走动找到关键得分点,然后通关游戏.入门Unity3D做的第一款游戏,比较无聊,但实现了一般的游戏功能.如,人物控制,碰撞检测,主控制 ...

  7. C# ASP .NET WEB方向和WPF方向,我该如何去选择

    一个2012年南航毕业学软件的学生,该如何去选择我的职业方向? 2011年11分月份,我被老师介绍在南京珠江路华丽国际大厦工作,开发一个大型国际物流平台,公司的开发人员比较少,设计网站的是高校的老师, ...

  8. matlab和本机MySQL链接

    1.安装好 ***matlab*** 和 ***mysql***: 2.[下载](http://dev.mysql.com/downloads/connector/j/#downloads) mysq ...

  9. 为什么数据可以从pl/sql查出来而使用ado.net查询,结果却是空?

    1.背景 一条记录(如select * from A where a='1'),使用pl/sql作为条件可以查询出记录,但用ado.net sql查询结果却是空. 2.原因 a字段的数据类型的char ...

  10. POJ 3553 Task schedule

    原题链接:http://poj.org/problem?id=3553 这道题主要就是贪心思想吧,对于每个job,根据其截止时间 dj 从小到大排序,我们必须要尽快把dj最小的job完成掉,这样才能使 ...