C++:类型转换

                    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 = 0;
    }
    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>0) cout<<"+";
  if(imag!=0) 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 0;
}

/*
说明:(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  0;
}
/*
 类型转换函数注意事项:
   (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 0;
}
/*
运行结果:
          Complex的对象转换为一个double类型的数据:22.2
          Complex的对象转换为一个int类型的数据:66
*/

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

#include <iostream>
using namespace std;
class Complex
{
public:
   Complex( ){real=0;imag=0;}  //默认构造函数
   Complex(double r){real=r;imag=0;}//转换构造函数
   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(3,4),c2(5,-10),c3;
   c3=c1+2.5; //复数与double数据相加,程序中不必显式地调用类型转换函数,它是自动被调用的,即隐式调用
   c3.display( );//c1+2.5----->c1+Complex(2.5)
   return 0;
}

注意,在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( );
其余部分不变。程序在编译时出错,原因是出现二义性。

时间: 2024-10-08 02:17:16

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

More Effective C++

条款一:指针与引用的区别 指针与引用看上去完全不同(指针用操作符'*'和'->',引用使用操作符'.'),但是它们似乎有相同的功能.指针与引用都是让你间接引用其他对象.你如何决定在什么时候使用指针,在什么时候使用引用呢? 首先,要认识到在任何情况下都不能用指向空值的引用.一个引用必须总是指向某些对象.因此如果你使用一个变量并让它指向一个对象,但是该变量在某些时候也可能不指向任何对象,这时你应该把变量声明为指针,因为这样你可以赋空值给该变量.相反,如果变量肯定指向一个对象,例如你的设计不允许变量为

Javascript类型转换的规则实例解析

http://www.jb51.net/article/79916.htm 类型转换可以分为隐式转换和显式转换,所谓隐式转换即程序在运行时进行的自动转换,显式转换则是人为的对类型进行强制转换.Javascript的变量是松散类型的,它可以存储Javascript支持的任何数据类型,其变量的类型可以在运行时被动态改变.请看示 例: ? 1 2 3 var n = 10; n = "hello CSSer!"; n = {}; 上面的示例中,首先声明n变量并初始化其值为10(整数类型),接

进制、类型转换、提升

进制 java支持四种进制表示 进制 示例 前缀 备注 十进制 int x = 10;     二进制 int x = 0b10; 0b或0B 计算机储存 八进制 int x = 010; 0 兼容以前程序 十六进制 int x = 0xceaf 0x或0X 0~9,a~f 细节: 一个十六进制位可以表示四个二进制位 当数值位数较多时,可以使用下划线对数字进行隔开,例:1_230_456 字面常量 整数:字面常量为int型,如果要表示long类型的字面常量,使用L或l做后缀,建议使用L,因为字母

第二节 变量 、 基本类型 、 运算符 、 表达式 、 数据 、 类型转换 、 常量

一:变量 定义:在程序运行中随时可以发生变化的量 变量声明:变量的声明只能以数字,字母,下划线,且字母不能开头,同时不能是C#中的关键字. 变量使用:变量必须先声明才能使用,变量赋值必须是对应类型,int age=true:这样就会报错. 二:常量 定义:在程序的生存期内不发生更改的不可变值 常量声明:const关键字  public const int age=10; age在程序内不会变,值一直是10: 三:内置数据类型(数值类型和非数值类型) 数值类型:分为整型和非整型 整型如下图: 非整

03 php 数据类型:整数,进制转换,浮点,字符,布尔,数组,空类型,类型转换,算术运算,比较运算

03 数据类型:整数,进制转换,浮点,字符,布尔,数组,空类型,类型转换, 算术运算,比较运算,逻辑运算,短路现象, 三目运算符,字符型运算: 数据类型 整体划分 标量类型: int, float, string, bool 复合类型: array,     object 特殊类型: null,     resouce 整数类型int, integer 3种整数表示法 十进制写法:123: $n1 = 123; 八进制写法: 0123 $n2 = 0123; 十六进制写法: 0x123 $n3

java 复习 - 数据类型转换

基本数据类型转换两天原则 低精度的值可以直接赋值给高精度的变量,直接变成了高精度 高精度的值不可以直接赋值给低精度的变量. 不同类型变量混合运算之后,得到的结果是精度最高的类型 基本数据类型和字符串之间的转换 基本数据类型转换成字符串 使用String 的valueOf()函数. 使用方法: String.valueOf(各种基本类型)  得到一个字符串.例子如下:  package typeConvertTest; public class TypeConvertTest{  public s

基本数据类型转换

自动类型转换:容量小的数据类型自动转换成容量大的数据类型.            char                           int long float double byte     short 一字节是8位,一字是2字节. 有多种类型的数据计算时.系统会将所有的数据类型转换成最大的数据然后进行计算. byte short char之间不会自动转换,他们三者计算会首先转换成int在进行计算. 当把任何基本类型的数据和自负类型的数据进行链接运算(+),得到的是字符类型的数据.

C++强制类型转换操作符 const_cast

const_cast也是一个强制类型转换操作符.<C++ Primer>中是这样描述它的: 1.将转换掉表达式的const性质. 2.只有使用const_cast才能将const性质性质转化掉.试图使用其他三种形式的强制转换都会导致编译时的错误.(添加const还可以用其他转换符,如static_const) 3.除了添加const或删除const特性,使用const_cast符来执行其他任何类型的转换都会引起编译错误.(volatile限定符也包括,不过我不怎么了解,本文主要说const)

Objective-C数据类型、数据类型转换

数据类型 1.Objective-C数据类型可以分为:基本数据类型.对象数据类型和id类型. 2.基本数据类型有:int.float.double和char类型. 3.对象类型就是类或协议所声明的指针类型,例如: NSAutoreleasePool *pool ,其中,NSAutoreleasePool是一个类,NSAutoreleasePool *是它指针类型或叫对象类型. 4.id类型可以表示任何类型,一般只是表示对象类型,不表示基本数据类型,所以刚才的变量可以声明pool也可以声明为id