• 第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 转换函数和友元函数

  • 相关阅读:
    获取时间对象
    定时器
    undefined与return
    获取设置非行间样式
    NaN
    return,break与continue的区别
    数据类型
    程序的机器级表示
    计算机内数字的表示
    计算机系统漫游
  • 原文地址:https://www.cnblogs.com/gaiqingfeng/p/16462821.html
Copyright © 2020-2023  润新知