C++ 运算符重载,类型转换

1、

运算符重载

规则和方法
  • 例如向四则运算符,+ - * / 原本只能用于基本类型计算,但是使用中难免会出现,类类,类基本,基本*类,像这样的运算。
    1. 使用类成员函数重载运算符。使得该类可以使用被重载的运算符进行自定义运算,其中第一个操作符为该类 例如:时间 + 时间,时间*n
    2. 使用友元函数重载运算符。可以实现形如 n*时间 的计算,需要在类中的声明前 加上 friend 表明是友元,在类外部实现友元函数无需使用friend。在友元函数中可以访问类中的私有成员。

class Time
{
private :
    int hours;
    int minutes;
public :
    Time(int h, int m){ hours = h; minutes = m; }
    Time() {};
    void showTime()
    {
        cout << "Time :" << hours << " : " << minutes << endl;
    }

    Time operator + (const Time & ) const;
    Time operator * (const int & )const;
    friend Time operator *(const int & n, const Time &t);
};
Time Time::operator + (const Time & t) const
{
    Time sum;
    sum.minutes = minutes + t.minutes;
    sum.hours = hours + t.hours + sum.minutes / 60;
    sum.minutes %= 60;

    return sum;
}
Time Time::operator*(const int & n) const{
    Time t;
    t.minutes = minutes*n % 60;
    t.hours = hours*n %24 + minutes*n/ 60;
    cout << "调用1" << endl;
    return t;
}

Time operator *(const int &n, const Time & t)
{
    Time mul;
    mul.minutes = (t.minutes )* n % 60;
    mul.hours =( t.hours) * n %24 +t.minutes*n / 60;
    cout << "调用2" << endl;
    return mul;
}
int main()
{
    Time a = { 5, 20 };
    Time b = { 3, 10 };
    Time c = a + b; 

    Time d = b * 7;
    d.showTime();

    Time e = 7 * b;
    e.showTime();
    cin.get();
    return 0;
}
  • 重载运算符 <<比较特殊,可以如下实现
void operator << (ostream & os, const Time & t)
{
    os << t.hours << " : " << t.minutes << endl;
}

image

  • 会发现单个输出,没有问题,连串输出后会有如上错误。原因在于重载原型要求使用的规则是这样的:
ostream << Time //然而,分解 cout <<e <<d;实际上是 
void(ostream <<Time) << Time; //所以问题在于返回值。 

改为如下:

ostream & operator << (ostream & os, const Time & t)
{
    os << t.hours << " : " << t.minutes << endl;
    return os;
}

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

  • 在基本类型的使用中常常见到的规则就是类型转换。如果右值类型与左值类型不匹配,若是各种兼容的数值类型,则可以隐式转换成左值类型。如下:
long count =8;
double time 11;
int side =3.33;
  • 在类的使用过程中有一个特点,编译器会自动根据初始化类型调用相应的构造函数。基于自动调用和基本类型自动转换的特点形成了 类的自动类型转换。有如下测试:
class Tree{
private :
    double height;
public:
    Tree(){}
    Tree(const double h) {
        height = h;  
        cout << "调用构造 height:"<<h << endl; }
};
int main()
{
    Tree tr1;
    int a = 5;
    tr1 = a;

    cin.get();
    return 0;
}

image

  • 可以看出确实也是隐式进行转换。转换的主要点是 初始化实参和构造函数形参之间的类型转换,内部如何转化是用户自定义的
  • 这种隐式转换是可以被控制的,因为这种转换可能隐藏某些潜在的问题。使用关键字explict可以关闭这种隐式转换。只能进行显示转换,也就是强制转换。在声明前加上explicit,如下
explicit Tree(const double h)

image
- 此时隐式调用将会报错,编译器找不到一个构造函数可以将 int进行转换。

转换函数

  • 见过可以将基本类型转换成类的方法,是否有将类对象转换成基本类型的方法呢?答案是有的。三点注意
    1. 转换函数必须是类方法
    2. 转换函数不能指定返回类型
    3. 转换函数不能有参数
//格式如下:
operator int(){ return height; }

测试代码:

class Tree{
private :
    double height;
public:
    Tree(){}
    Tree(const double h) {  height = h;  }
    operator int(){ return height; }
};
int main()
{
    Tree tr1(5);
    int b = tr1;
    cout << "obj->int tr1: "<< tr1<< endl;
    cout << "obj->int  b : " << b << endl;
    cin.get();
    return 0;
}
  • 可以看出,对象根据自定义的转换函数转成了相应的基本类型。当要输出对象时,编译器可以自动选择唯一的准换函数,编译器只有唯一选择。然而如果还有其他选择,例如:
public:
    Tree(){}
    Tree(const double h) {  height = h;  }
    operator int(){ return height; }
    operator double(){ return height; }

image

  • 可以看到如下错误,这点是不难理解的,所以在多个转换函数存在的情况下,应该显示指明转换目标,如下所示:
Tree tr1(5.6);
int b = tr1;
cout << "obj->int tr1: "<< double(tr1)<< endl;
cout << "obj->int  b : " << b << endl;

image

  • 和类的自动转换类似,也可以使用explicit 限定不能进行隐式转换,只能显示指明转化调用。
explicit operator double() const ;
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值