14C++类的类型转换

 .类的类型转换
(前言,定义,基类与派生类,设计指导)
1.前言
内置类型(int,double,float,char,bool)的转换
1.1内置类型隐式转换
因为内置类型有转换功能,自然类,派生类也会引入转换功能,
我们先看一下内置类型转换
.在赋值时,编译器始终以=的左操作数类型为标准进行转换
Int i1=25,i5;
Double d1=5.65;
i2=i1+d1;            //因左操作数是int,d1的double自然转换为int,被简化为5
结果i2=30
.在表达式计算时,编译器通常以最大的数值最大的为标准进行转换
Char->int->float->double
Bool v;
V=i1>=d1; //因为是在表达式中,int自动转换为double参与比较运算
.指针转换为bool
Int *pi;
If(*pi);               //自动转换为bool类型
While(*pi) //自动转换为bool类型
.int与bool转换
Bool b=true;
Int iv1=b;                   //bool自动转换为int,iv1=0
Double d1=3.12
Bool a=d1;          //double自动转换为1,非0即true,结果bool=true
1.2C++原来老的转换方式
它存在的理由是为了支持旧的C++向后兼容而支持的语法
Type (express)
(type)express //如float f1=(float)d1+float(int1);
 
1.3命名的强制转换C++新引入的特性
cast-name<type> (expression).
.dynamic_cast(用于继承和运行时的指针和引用的动态识别)
 
.const_cast(把const对象转换为非const,让它可以修改)
Const char* pstr;
Char* p1=string_copy(const_case<char*>(pstr));
.static_cast(去掉隐式转换的编译器警告)
当编译器将一个较大的算术类型赋值给较小的类型时,编译器通常会警告,说会发生精度丢失,
用static_cast后,就会关闭编译器的精度丢失警告!
Double d=69.36;
Char ch=static_cast<char>(d);
.reinterpret_cast
这个用的非常少,不同的编译器有不同的规定,必须查阅相关编译器的手册说明
 
2.定义
在内置类型,基类,派生类自然都存在转换运算
类型转换共有以下几个形式
1.       内置数据类型的隐式转换
(小类型到大类型转换,精度不影响,由大类型到小类型转换,精度会减少,)
2.       内置数据类型的显示转换(表达式前面添加转换类型符号)
3.       C++引入的4个强制类型转换()
4.       类的类型转换
 
3.基类与派生类
3.1类的类型转换
类的转换操作符是一种特别的类成员函数,在类体声明并实现,
格式如 class classid{operator type() const {return 成员变量;}};
代码如
class smallint{
public:
operator int() const {return int_a;}        //类型转换成员函数
Private:
Int int_a};
特别说明:类型转换成员函数不能有返回值,不能有形参
3.2类的几种转换类型
.在表达式中: smallint sm1;double d1; sm1>d1;//sm1类对象转换为double
.在条件中:if (sm1) //自动由int转换为bool
.在函数中:smallint s1; char c1=get(s1) //从函数返回值由int转换为char
.在cout中:cout<<s1; //把s1转换为ostream流对象,这类中就是重载<<
.在cin中:cin>>s1; //把s1转换为istream流对象,这类中就是重载>>
.传统强制转换: double d1=(double)s1; //把类的对象s1强制转换为double
.新型强制转换:float f1=static_cast<float>(s1); //把s1对象强制转换为float
 
3.2基类和派生类之间的转换
3.2.1.基类到派生类的转换
从基类到派生类的自动转换方式是不行的,包括指针,如果要用就得使用dynamic_cast指定
因为派生类里新添加的成员,基类未必有
//class base{…};
//class subbase :public base{…};
 Base base1;
Subbase sub1=base1; //error,严重错误,派生类会有部分成员未初始化,函数访问出错
.当基类有虚函数,派生类实现了基类的虚函数时,可以用dynamic_cast转换符号
把基类的指针强制转换成派生类的指针,代码如下:
subclass *sub=dynamic_cast<subclass*>(baseptr)
//把基类指针baseptr强制转换为派生类指针subclass*,并赋值给派生类的指针*sub
If (subclass *sub=dynamic_cast<subclass*>(baseptr))
…操作派生类的代码
Else
..操作基类的代码
***注意
在使用基类到派生类的强制转换时,两个类的数据成员最好相同,派生类数据成员是直接继承基类的
3.2.1.派生类到基类的转换
用派生类到到基类的转换只有两种方式(引用和复制)
1复制:在基类可以用复制构造函数和=运算符把派生类直接
 
Class derived;
Class base{
Public:
        base(const derived&); //ok,用派生类的基类部分成员来初始化给基类的数据成员
        base& operator=(const derived&);//OK,同上
};
Derived d1;
Base b1(d1);               //OK,用派生类直接生成基类的对象b1,调用基类的复制构造函数
Base b2=d1;                //OK,建立基类对象b2,用派生类d1初始化b2,调用基类的=函数
以上这种做法非常少用
 
2.派生类到基类的引用
2.1.在派生类直接使用基类函数,防止派生类同名函数覆盖基类函数
Class derived;
Base *b1=& derived; //用派生类生成基类对象
double d=b1->base::get_amount(25);//直接使用基类::基类虚方法
2.2通过在派生类直接使用基类的引用或者指针来调用基类或者派生类的方法
如果基类有虚函数成员,派生类实现了基类的虚函数
Class base{ //基类
Public:
Virsual get_amout(int qty){return price*qty;}
Print(const base&);
Protected:
Int qty;
Double price;
};
Class derived :public base{ //基类
Public:
double get_amout (int qty)
{if qty>=minqty return qty*(1-rate)*price; else return qty*price; }
private:
Int minqty;
Double rate;
};
调用这两个类的其它函数,它不是基类和派生类的任何成员函数
下面这个函数是用上面的两个类组合成另外通用函数
Void Print (ostream os&,const base & b1){cout<< bq.get_amount();}
 
//类函数调用代码,这就是把动态绑定调用,编译器在运行程序后,
才能确定调用的参数是在基类还是派生类,不同的类的对象自动调用不同类的对应函数
Base base1;
Derived derived1;
Print (cout,derived1); //调用派生类的get_amout
Print (cout,base1);               //调用基类的get_amout
 
5.       设计指导
.不要过分的对类进行类型转换
.一个类只支持一个类型转换
.从基类的到派生类的是不会自动转换!
.当基类是有虚函数,在派生类的虚函数的是对基类的引用时,
在程序运行后,才能知道应该调用是基类还是派生类的成员函数,这个转换大家一定要搞清楚
 
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值