第十一章 使用类
2020-02-24 10:41:40 4 举报
AI智能生成
登录查看完整内容
C++ plus
作者其他创作
大纲/内容
使用类
运算符重载
原理
C++根据操作数的数目和类型决定采用哪种操作
格式
原型
void(返回类型)operator op( argument - list )
例子
void operator *( )表示重载*运算符
说明
Time 一点要有吗?不是说可用于非成员函数吗?//非成员且非友元重载运算符一定要有一个参数为自定义对象。友元也是这样吧。
调用
void Time::operator +( ... ){}
计算时间(运算符重载例子)
源代码(不用重载)
#include<iostream>class Time{private://可有可无 \tint hours;\tint minutes;public:\tTime();//构造函数没有返回类型 span class=\"Apple-tab-span\" style=\"white-space:pre\
用重载
修改
Time Sum( const Time & t )const;
Time operator+( const Time & t )const;
Time Time::Sum( const Time & t ) const//传递引用的效率更快 {\t.......\t}
只改函数头!!Time Time::operator+( const Time & t )const{}
total = codding.Sum(fixing);
total = codding+ fixing;
相当于total.operatr+( fixing )
total = codding+ fixing; = codding.operatr+( fixing )
+左边是调用对象,右边是作为参数被传递的对象
重载限制
前言
重载的运算符(有些例外)不必是成员函数,但必须至少有一个操作数是用户自定义类型
???不必是成员函数???操作数是比如+的两边,可以是友元函数,也可以是普通函数,但必须有一个参数是自定义类,否则会出错。
限制
重载的运算符不必是成员函数。(可以是友元函数、也可以是普通函数)重载后的运算符必须至少有一个操作数是用户自定义类型。
如果是成员函数,第一个操作数一定是用户定义类。
使用运算符时不能违反运算符原来的句法规则。
不能将求模运算符(%)重载为使用一个操作数。
int x;Time shiva;% x;% shiva;//不太懂。。
不能改变运算符的优先级
不能创建新运算符
不能定义operator**( )函数来表示求幂。
不能重载下面的运算符
sizeof
. 成员运算符
.* 成员指针运算符
:: 作用域解析运算符
?: 条件运算符
typeid 一个RTTI运算符
onst_cast 强制类型转换运算符
dynamic_cast 强制类型转换运算符
tatic_cast 强制类型转换运算符
只能通过成员函数重载
=
()函数调用运算符
[] 下标运算符
-> 通过指针访问类成员的运算符
可重载的P388
友元
作用
可以访问类对象的私有部分,函数与类的成员函数有相同的访问权限
应用
重载运算符+时候,只能 对象*double数值 形式,使用友元可以 double * 对象 有效。
类型
友元函数
友元类
友元成员函数
后两种15章
创建
原型放在类声明中
虽然在类声明中定义,但不是成员函数,不能用成员运算符来调用
函数定义
不是成员函数,所以不用Time::x限定符
有了以上定义 可以 A = 2.7 * B;
用成员函数处理私有值,所以可以不必是友元,但一般都会弄成友元。不必是友元,因为没有处理私有数据
重载<<
功能
重载位置
在Time 类中声明为一个友元函数,在iostream 类中声明危险
友元的原因如果是成员函数,需要tirp<<cout形式
定义
ostream类对象,有cerr,有ofstream类对象
可以输入到文件中。ofstream File(\"...\");Time tirp(...);File<<tirp;
类继承能够让ostream 引用能够指向ostream对象和ofstream 对象
ostream 在名称空间std,所以要写成 std::ostream 形式。
重载运算符:作为成员函数还是非成员函数
对于狠多运算符,可以选择使用成员函数或非成员函数实现运算符重载。
一般非成员函数应该是友元函数。
两个都是类对象时候,只能选择其中一个,不然会产生二义性
再谈重载:一个矢量类
特点
在同一个对象中包含两种描述同一样东西的不同方式
矢量
什么是矢量?
有大小和方向的量,所以应该创建一个类表示矢量
描述
方式1
大小(长度)和方向(角度)描述
方式2
分量 x 和 y 描述
可以在一个类中同时定义两种方式来描述矢量
P400代码
代码400
类的自动转换和强制类型转换
初始化的方式
Stock sally(.....);Stock sally=Stock(.......);C++11:Stock sally={....};Stock sally{....};
内容
基本类型转换为类
自动转换
强制转换
类转换为基本类型
基本类型
可以是int double...
隐式转换(自动转换)
使用Stone(double)情况。隐式转换
将Stonewt对象初始化为double
Stonewt myCat(19.7)....Stonewt myCat=Stonewt(19.7)//这个是显式转换吧。??
将double值赋给Stone对象
情况2
将double值传递给Stone参数
返回值声明为Stonewt类,但返回double值
在上述任意一种情况下,使用可转换为double类型的内置类型
Stone June(7000)June = 9300 7000和9300都不是double,但是会转换为double . 如果构造函数还定义了Stonewt( long )形式,则上两条是错误的,有二义性。
前提:构造函数
(原型)StoneWt( double )StoneWt myCat( 19.6 ),其实就是意味着把double 转换为StoneWt对象
StoneWt myCat;myCat = 19.6;
使用构造函数StoneWt(double)创建一个临时的Stone对象,将19.6作为初始化值。采用成员赋值方式将该临时对象的内容复制到myCat中。称为隐式转换。
使用到了构造函数,赋值函数。
构造函数只有一个参数才能够这样
显式转换
myCat=Stonewt(19.6)//不是相当于调用构造函数吗
myCat=(Stonewt)19.6;
关闭自动转换方法只能使用显式转换
方法
前缀explicit
声明构造函数原型:explicit Stonewt( double lbs );
定义不用吗?对
myCat = 19.6// no okmyCat=Stonewt(19.6)//OKmyCat=(Stonewt)19.6;//OK
其它、对于char类型的
已知前提
隐式转换/显式转换
Star north;north = \"polaris\";north = Star(\"polaris\");
转换函数(类转换为基本类型)
operator double( );//转换为double类型operator int( );//转换为int类型
转换函数必须是类方法
不能指定返回类型
不能有参数
最好声明为const类型.operator double( ) const;
不是const会有什么情况???
Stonewt::operator int() const{ return int( pounds + 0.5 );//四舍五入}
Stone::operator double() const{ return pounds;}
Stone::operator int*() const{....}//转换成int*类型也可以。
返回什么数据成员要自己写。
Stonewt wolf(258.5);double host = doubel(wolf); = (double)wolf;
隐式转换
注意说明
1
如果同时定义了 operator double( ); operator int( );Stonewt dog;long gone = dog;//错误,二义性long gone = (double )dog;//可以。cout<<dog;//no ok。没有重载<<,只有一个double 或int转换时候可以,输出转换函数的返回类型。//???
2
Stonewt ius(6.0);Stonewt lux=ius+20.2//ambiguous不知道是将ius转换为double还是20.1转换为Stonewt
关闭隐式转换方法
原型加explict
public:.....explict operator double() const;
定义一个功能相同的非转换成员函数
int Stonewt::Stone_to_int();{ return XX;}int plb = dog.Stone_to_int();int plb =dog;//这样是非法的。
转换函数和友元函数(加法的类型转换)
前提
假设没有定义operator double()转换函数
重载了运算符+:
参数都是类对象
情况1
Stonewt a( 9.12 );double b = 146.0;Stonewt total;total = a+b;
成员函数可以,友元函数可以
Stonewt(double )将 b 对应的参数转换为了类对象
情况3
Stonewt a( 9.12 );double b = 146.0;Stonewt total;total = b+a;
成员函数不可以,不会试图将b转换为Stonewt对象。(因为转换的是)成员函数参数。
实时加法选择
方法一
优点
程序简短。
缺点
增加时间内存开销
方法二
运行速度快
程序长
选择
经常使用double Stonewt加法——方法二,不然方法一。
问题
什么时候不会将。。。转换成临时的类对象//??eg:1.上:Stonewt a( 9.12 );double b = 146.0;Stonewt total;total = a+b;
会创建的原因:有Stonewt(double )构造函数。
其他
Complex Complex::subComplex(Complex &c){\tComplex sub;\tsub.real=real-c.real;\tsub.imaginary=imaginary-c.imaginary;\treturn sub;}
类内嵌对象(类的组合)
含义
一个类里面的数据成员是另一个类的对象,即内嵌其他类的对象作为自己的成员。
代码
构造函数处理方法
语法
(类型名)::(类型名) : 内嵌对象1(形参表),内嵌对象2(形参表)
复制构造函数
对比
Line::Line(Line &1){ start=l.start; end=l.end;}
上做法是可以的。
现象:如果类中有内嵌类对象,在创建对象时,先创建内嵌的类对象。
即Line line1(....)先创建line1 中的point 类start end对象。先调用的是point 类的构造函数。再调用line 的构造函数
如果没有初始化列表,先调用point类的默认!构造函数。在调用Line 的构造函数。
析构函数的调用执行顺序与构造函数相反
代码说明
局部
由上可看出,用初始化列表初始化类对象的效率更高。
系统默认函数
初始化类成员时,使用相应类的复制构造函数
赋值运算符
数据成员如果是类,默认成员赋值使用相应类的赋值运算符
0 条评论
回复 删除
下一页