第11章 使用类

<c++ primer plus>第六版

11 使用类

11.1 运算符重载

函数重载/函数多态: 定义多个名称相同但特征标不同的函数.
运算符重载是一种形式的c++多态, 将重载的概念扩展到运算符上.

运算符函数, 是一种特殊函数形式, 格式如下:

operatorop(argument-list);

其中op必须是有效的c++运算符, 不能虚构新运算符.

例如

operator+()  //重载+运算符
operator*()  //重载*运算符
operator[]() //重载[]运算符(数组索引运算符)

如下语句:

district2 = sid + sara;          //编译器将使用运算符函数替换上述运算符:
district2 = sid.operator+(sara); //该函数隐式地使用sid, 显式地使用sara.

11.3 友元


通常, 访问类的途径只能通过公有类方法. 但这种限制太严, 所以提供了另外形式的访问权限: 友元.
友元有3种: 友元函数, 友元类, 友元成员函数.


为何需要友元函数:
对于 A = B * 2.75; 转换为 A = B.operator*(2.75);
但 A = 2.75 * B, 由于2.75不是自定义的类对象, 编译器没办法使用成员函数调用来替换该表达式.
解决方法:

  1. 限制只能按 B*2.75方式写, 这样对客户不友好.
  2. 使用非成员函数:
    函数原型: Time operator(double m, const Time & t);
    则 A = 2.75 * B; 替换为 A = operator
    (2.75, B);

但使用非成员函数引发了一个新问题: 常规非成员函数不能直接访问类的私有数据,
于是提出特殊的非成员函数, 它可以访问类的私有成员, 被称为友元函数.


11.3.1 创建友元

//第一步, 将原型放在类声明中, 并加friend关键字.
friend Time operator*(double m, const Time & t);

//第二步, 编写函数定义, 由于不是成员函数, 所以不需要Time::限定符. 且不需要在定义中使用friend关键字.
Time operator*(double m, const Time & t)
{
    Time result;
    ... //访问t的私有数据
    return result;
}

类的友元函数是非成员函数, 但访问权限与成员函数相同.

注意, 只有类声明可以决定哪些函数是友元, 因此类声明仍然控制了哪些函数可以访问私有数据.

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

cout是一个ostream对象, 它能够识别所有c++基本类型(因为对每个基本类型, ostream类声明中都包含了相应的重载的operator<<()定义).

要使cout能识别Time对象, 对<<进行重载, 可以这样显示对象:

cout << trip ;

一般来说, 要重载<<运算符来显示C_NAME的对象, 可以使用一个友元函数, 定义如下:

ostream & operator<<(ostream & os, const C_NAME & obj)
{
    os << ...; //显示对象内容
    return os;
}

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

加法运算重载

成员函数版本 :

Time operator+(const Time & t) const;
T1 = T2+T3 //转换为 T1 = T2.operator+(T3);

非成员函数版本:

friend Time operator+(const Time & t1, const Time & t2); 
T1 = T2+T3 转换为 T1 = operator+(T2, T3);

成员函数版本少一个参数, 这个参数通过this指针隐式地传递.

11.5 再谈重载: 一个矢量类

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

兼容的内置类型的转换

long count = 8;   //将整型值8转换为long类型
double time = 11; //将整型值11转换为double类型
int side = 3.33;  //将双精度值3.33转为整型值3

不兼容类型不能自动转换

int * p = 10; //错误, 不能把整数赋值给指针
int * p = (int *) 10; //正确, 将10强制转为int指针类型(int *), 再将指针赋值给p.

11.6.1 转换函数

Stonewt wolfe(285.7); //double类型转换为Stonewt类型
double host = double(wolfe);     //将Stonewt类型转换为double类型, 语法1.
double thinker = (double) wolfe; //将Stonewt类型转换为double类型, 语法2.

Stonewt wells(20, 3);
double star = wells; //左侧double, 右侧Stonewt, 编译器将寻找转换函数(如果找不到, 将报错)

转换函数的定义方法:

operator typeName();

如:

operator double(); //转换为double类型的函数

注意:

  1. 转换函数必须是类方法;
  2. 转换函数不能指定返回类型;
  3. 转换函数不能有参数;
#ifndef STONEWT1_H_
#define STONEWT1_H_
class Stonewt
{
...
public:
    operator int() const;
    operator double() const;
}

#endif


Stonewt::operator int() const //最后一个const表示是const函数, 不修改类成员
{
    return int(pounds + 0.5);
}

11.6.2 转换函数和友元函数

posted @ 2022-07-10 11:18  编程驴子  阅读(20)  评论(0编辑  收藏  举报