第十一章 使用类

本文介绍了C++中的运算符重载,通过Time类展示了如何使用`operator+`实现时间相加。同时,讨论了友元函数的概念和作用,解释了为何友元函数可以访问类的私有成员,并给出了友元函数用于重载`*`运算符的例子。此外,还提及了类的隐式类型转换和显式类型转换,以及如何使用`explicit`关键字控制转换行为。
摘要由CSDN通过智能技术生成

运算符重载

运算符重载的形式是:

operator op (argument-list)

其中op必须是现有的运算符才可以重载,例如 + - * / []等

operator + () 重载+运算符
#ifndef __OPERTOR_TIME_H__
#define __OPERTOR_TIME_H__

void start_opertor_time_eng();
class Time {
    private:
        int hour_;
        int minutes_;
    public:
        Time();
        Time(const int hour, const int minutes);
        void addMin(int minutes);
        void addHr(int hour);
        void reset(int hour = 0, int minutes = 0);
        Time sum(const Time & t) const;
        void showTime();
        Time operator+(const Time & t) const;
        ~Time();
};
#endif //__OPERTOR_TIME_H__
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include "operator_time.h"

using namespace std;

void start_opertor_time_eng() {
    cout << "start_opertor_time_eng." << endl;
    Time *t1 = new Time(3, 20);
    Time *t2 = new Time(4, 30);
    Time tsum1 = t1->sum(*t2);
    tsum1.showTime();
    Time tsum2 = t1->operator+(*t2);
    tsum2.showTime();
    Time tsum3 = *t1 + *t2;
    tsum3.showTime();
    delete t1;
    delete t2;
}

Time::Time(){
    hour_ = 0;
    minutes_ = 0;
    cout << "Default Constor." << endl;
}

Time::Time(const int hour, const int minutes) {
    hour_ = hour;
    minutes_ = minutes;
    cout << "Constor Time." << endl;
}

void Time::addMin(int minutes) {
    minutes_ += minutes;
    hour_ += minutes_ / 60;
    minutes_ %= 60;
    cout << "addMin:" << minutes << endl;
}

void Time::addHr(int hour) {
    hour_ += hour;
    cout << "addHr:" << hour << endl;
}

void Time::showTime() {
    cout << "showTime: Time: " << hour_ << ":" << minutes_ << endl;
}

void Time::reset(int hour, int minutes) {
    hour_ = hour;
    minutes_ = minutes;
    cout << "reset:" << endl;
}

Time Time::sum(const Time & t) const {
    cout << "sum" << endl;
    Time sum;
    sum.addHr(this->hour_ + t.hour_);
    sum.addMin(this->minutes_ + t.minutes_);
    return sum;
}

Time Time::operator+(const Time & t) const {
    Time sum;
    sum.addHr(this->hour_ + t.hour_);
    sum.addMin(this->minutes_ + t.minutes_);
    cout << "operator+" << endl;
    return sum;
}

Time::~Time() {
    cout << "~Time" << endl;
}

如上例程所示,如果要使用符号重载,只需要将sum替换为 operator+ 就行,

当调用Time tsum3 = *t1 + *t2; 时候,编译器实际上是调用函数Time Time::operator+(const Time & t); 注意 + 号左侧为调用对象

Time Time::sum(const Time & t) const {
    cout << "sum" << endl;
    Time sum;
    sum.addHr(this->hour_ + t.hour_);
    sum.addMin(this->minutes_ + t.minutes_);
    return sum;
}

Time Time::operator+(const Time & t) const {
    Time sum;
    sum.minutes_ = (this->minutes_ + t.minutes_) % 60; 
    sum.hour_ = this->hour_ + t.hour_ + sum.minutes_ / 60;
    cout << "operator+" << endl;
    return sum;
}

// 有趣的是Time类的成员函数sum可以直接访问t和临时变量sum的私有成员。
为什么呢,sum函数不属于任何一个对象,同一个类对象,所以可以直接访问任何一个Time类对象的私有成员吗。
所以访问控制是针对类的,不是针对对象的

友元

包括三种:友元函数,友元类,友元成员函数。

友元函数

通过让函数称为类的友元,让该函数具有和类的成员函数相同的访问权限。

Time Time::operator*(int n);

如上边的重载,如想Time t =  2 + time1;这种调用是不可行的,因为+ 左边为调用对象。

所以解决此问题可以用Time类的非成员函数。

Time operator*(int n, Time t); // 使用方法 Time t1 = 2 * t; *号左边对应第一个参数n,右边对应第二个t

Time operator*(int n, Time t) {
    Time sum;
    sum.minutes_ = (t.minutes_ * n) % 60;
    sum.hour_ = t.hour_ * (sum.minutes_ * n) / 60;
    cout << "operator*" << endl;
    return sum;
}

如上所示,但是存在问题,外部函数无法访问类的私有变量。这时候友元函数派上用场了。

创建友元

第一步:在类声明中加入友元函数声明,并用friend修饰,

●友元虽然是在类中声明的,但并不是类成员函数,所以不能用成员运算符调用。

●虽然友元函数不是类成员函数,但是和成员函数一样具有私有成员访问权限。

friend Time operator*(int n, Time t); 可以看成目的是让类授予此函数访问权限。

第二步:定义友元函数

友元函数的定义不能friend修饰,由于不是成员函数,不能写Time::

利用友元函数重载 <<符号

ostream& operator<<(ostream& os, Time t) {
    os << t.hour_ << "hour " << t.minutes_ << "minutes" << endl;
    return os;
}

只需要在类中声明加上friend
        friend std::ostream& operator<<(std::ostream & os, Time t);

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

接受一个参数的构造函数为将类型与该参数相同的值转换为类提供了蓝图。

例如 Stonewt(double lbs); 此构造函数可以用于将double类型的值转换为Stonewt类型。

这个过程是隐式转换,不需要显式强制类型转换。

Stonewt myCat;
myCat = 10.2;
//以上程序将使用10.2作为构造函数的参数,调用构造函数Stonewt(double lbs),
创建一个临时对象,然后赋值给mycat

如果构造函数是两个参数,是不能进行隐式转换的。

Stonewt(int stn, double lbs);

//但是第二个参数如果设置了默认参数,就可以转换int

Stonewt(int stn, double lbs = 15.6);

如果想关闭自动类型转换可以使用关键字explicit 修饰构造函数

explicit Stonewt(int stn, double lbs = 15.6); 这样将关闭隐式转换,但还是允许强制转换。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值