ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Chapter 11使用类

2021-12-26 19:02:21  阅读:175  来源: 互联网

标签:Chapter 11 友元 转换 函数 double 运算符 使用 重载


本章内容包括:

  • 运算符重载
  • 友元函数
  • 重载<<运算符,以便用于输出
  • 状态成员
  • 使用rand()生成随机值
  • 类的自动转换和强制类型转换
  • 类转换函数

11.1 运算符重载

运算符重载时一种形式的C++多态。
为了实现运算符重载,需要使用被称为运算符函数的特殊函数形式。运算符函数的格式如下:
operator op(argument-list)
op必须是有效的C++运算符,不能虚构一个符号。

11.2 计算时间:一个运算符重载示例

运算符重载operator+()之后,由于+是从左向右结合的。
t4 = t1 + t2 + t3 -> t4 = t1.operator+(t2 + t3) ->
t4 = t1.operator+(t2.operator+(t3))因此可以计算。

11.2.1 重载限制

以下是关于重载运算符的限制:

  1. 重载后的运算符必须至少有一个操作数是用户定义的类型,防止用户为标准类型重载运算符。例如不能用运算符-重载为计算两个double值的和。
  2. 使用运算符时不能违反运算符原来的句法规则。不能修改运算符的优先级
  3. 不能创建新的运算符。
  4. 不能重载下面的运算符。
  • sizeof
  • .:成员运算符
  • .*:成员指针运算符
  • :::作用域解析运算符
  • ?::条件运算符
  • typeid:一个RTTI运算符
  • const_cast:强制类型转换运算符
  • dynamic_cast:强制类型转换运算符
  • reinterpret_cast:强制类型转换运算符
  • static_cast:强制类型转换运算符
  1. 下表中的大多是运算符都可以通过成员函数或非成员函数进行重载,但下面的运算符只能通过成员函数进行重载。
  • =赋值运算符
  • ()函数调用运算符
  • []下标运算符
  • ->通过指针访问类成员的运算符

可重载的运算符

+ - * / % ^
& | ~= ! = <
> += -= *= /= %=
^= &= |= << >> >>=
<<= == != <= >= &&
|| ++ -- , ->* ->
() [] new delete new[] delete[]

11.3 友元

C++控制对类私有成员的访问,通常公有类方法是唯一的访问途径,但有时候这种限制太严格,以至于不适合特定的编程问题。C++提供可另一种形式的访问权限:友元。友元有三种:

  • 友元函数
  • 友元类
  • 友元成员函数
    友元函数给运算符重载提供了非成员函数访问类数据的方式。

11.3.1 创建友元

  1. 将其原型放在类声明中,在原型声明前加关键字friend:有两点含义
  • 友元函数在类中声明,但不是成员函数,因此不能使用成员运算符来调用;
  • 友元函数不是成员函数,但有相同的访问权限
  1. 编写函数定义

友员函数是拓展接口的组成部分。
如果要为类重载运算符,并将非类的项作为第一个操作数,则可以用友元函数来反转操作数的顺序。

11.3.2 常用的友元:重载<<运算符

一个很有用的类特性是可以对"<<"运算符进行重载,使之能够与cout一起来显示对象的内容。
重载该运算符使用的是输出类的友元函数,不是系统流类的友元函数。
需要注意的是该友元函数为了实现输出需要返回对象的引用,例:

friend std::ostream & operator<<(ostream & os, const class & c);

11.4 重载运算符:作为成员函数还是非成员函数

对于成员函数版本来说,一个操作数通过this指针隐式的传递,另一个操作数作为函数参数的形式显示的传递。对于友元版本来说,两个操作数都作为参数传递。
一些运算符只能作为成员函数重载,其他的视情况而定。

11.5 再谈重载:一个矢量类

11.5.1 使用状态成员

枚举变量RECT、POL被称为状态成员,其描述对象所处的状态。
多种表示方式和类
类非常适合于在一个对象中表示实体的不同方面。有两种表示方法,第一种方法,存储多种表示方式:具体分以下几步:

  1. 在一个对象中存储多种表示方式;
  2. 编写类函数,以便给一种表示方式赋值时,将自动给其他方式赋值。
    第二种方法存储一种表示方式,使用方法来提供其他表示方式。
    通过内部处理转换,类允许从本质上看待一个量。

11.5.2 为Vector重载算数运算符

如果方法通过计算得到一个新的类对象,则应考虑是否可以通过类构造函数完成这种工作,可以避免麻烦,同时确保新对象按照正确的方式创建。
运算符-有一元版本和二元版本,运算符/只有二元形式。

11.5.3 对实现的说明

将接口与实现分离式OOP的目标,允许对实现进行调整,而无需修改使用这个类的程序中的代码。
两种实现方式对应不同的情况。

11.5.4 使用Vector类来模拟随机漫步

rand()函数,返回一个从0到某个值的随机整数。
srand()函数允许覆盖默认的种子值,重新找一个随机数序列。
time(0)函数返回当前时间,通常为从某一个日期开始的秒数。

11.6 类的自动转换和强制类型转换

可以将类定义成与基本类型或者另一个类相关,使得从一种类型转换为另一种类型是有意义的。
类使用构造函数进行隐式转换,该构造函数作为转换函数。例:
Stonewt myCat; myCat = 19.6;
有两个参数的构造函数如果第二个参数有默认值,则可以作为构造函数。
如果不希望进行这种类型变换,可以用关键字explicit,例:
explicit Stonewt(double lbs);
在用explicit限定了构造函数之后,该构造函数只能用于显式强制类型转换。
下面的情况会用于隐式转换:

  • 将Stonewt对象初始化为double值时
  • 将double值赋给Stonewt对象时
  • 将double传递给接受Stonewt参数的函数时
  • 返回值被声明为Stonewt的函数试图返回double值时
  • 在上述任意一种情况下,使用可转换为double类型的内置类型时

当且仅当转换不存在二义性时,才会进行这种二步转换。

11.6.1 转换函数

将Stonewt对象转换为double值。
构造函数可以实现某种类型到类类型的转换;
相反的转换需要使用特殊的C++运算符函数——转换函数。operator typeName();
创建转换函数,需要注意以下几点:

  • 转换函数必须是类方法;
  • 转换函数不能指定返回类型;
  • 转换函数不能有参数。

typeName指出了要转换的类型,因此不需要指定返回类型。
自动应用类型转换
不存在二义性时,可以使用cout输出类,不需要定义。
用户不希望进行转换时,转换函数也可能进行转换。使用explicit可以取消这种自动类型转换。
除了使用explicit限定符,也可以用一个功能相同的非转换函数替换为该转换函数。
应谨慎的使用隐式转换函数,最好选择仅在被显示地调用时才会执行的函数。
C++为类提供下面的类型转换:

  • 只有一个参数的类构造函数用于将 类型与该参数相同的值 转换为 类 类型。在构造函数中声明explicit可以防止隐式转换,只允许显示转换。
  • 被称为转换函数的特殊类成员运算符函数,用于将类对象转换为其他类型。

11.6.2 转换函数和友元函数

实现加法时的选择
将double量和Stonerwt量相加,有两种选择:

  • 第一种方法将+函数定义为友元函数,构造函数将double隐式转换成Stonewt类型的参数。
  • 第二种方法时将运算符+重载为一个显式使用double类型参数的函数。

第一种方法,程序更简短,定义的函数较少;缺点是调用转换函数将增加时间和内存开销。
第二种方法,程序较长,运行速度较快。

11.7 复习题

1.使用成员函数为Stonewt类重载乘法运算符,该运算符将数据成员与double类型的值相乘,注意,用英石和磅表示,需要进位。也就是说,将10英石8磅乘以2等于21英石2磅。

Stonewt operator*(double n);
Stonewt Stonewt::operator*(double n)
{
	Stone multi;
	multi.pounds = pounds * n;
	multi.stone = int(multi.pounds) / Lbs_per_stn;
	multi.pds_left = int(multi.pounds) % Lbs_per_stn + multi.pounds - int(multi.pounds)
	return multi;
}

2. 友元函数和成员函数的区别是什么?
友元函数是类方法之外的函数,使用时不需要使用类作用域运算符,成员函数是类方法,使用时需要对象和类作用域运算符
成员函数是类定义的一部分,通过特定的对象来调用。成员函数可以隐式的访问调用对象的成员,而无需使用成员运算符。
友元函数不是类的组成部分,因此被称为直接函数调用。友元函数不能隐式的访问类的成员,而必须将成员运算符用于参数传递的对象。
3. 非成员函数必须是友元才能访问类成员吗?
非成员函数必须是友元才可以访问类的私有成员。
4. 使用友元函数为Stonewt类重载乘法运算符,该运算符将double值与Stonewt值相乘。

friend Stonewt operator*(double n, const Stonewt & st);
Stonewt operator*(double n, const Stonewt & st)
{
	return st * n;
}

5. 哪些运算符不能重载?

  • sizeof
  • .
  • .*
  • ::
  • ?:
  1. 在重载运算符=、()、[]和->时,有什么限制?
    必须作为成员函数重载。
  2. 为Vector类定义一个转换函数,将Vector类转换为一个double类型的值,后者表示矢量的长度。
operator double() const;
Vecotr::operator double() const
{
	return mag;
}

标签:Chapter,11,友元,转换,函数,double,运算符,使用,重载
来源: https://www.cnblogs.com/Fight-go/p/15731079.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有