c++对象和类(2)-重载、友元、类型转换

2018-07-08 07:48:57

运算符重载

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 Time & t) const
{
    Time diff;
    int tot1, tot2;
    tot1 = t.minutes + 60 * t.hours;
    tot2 = minutes + 60 * hours;
    diff.minutes = (tot2 - tot1) % 60;
    diff.hours = (tot2 - tot1) / 60;
    return diff;
}

里面函数参数就是运算符后面的值,前面代表类对象本身,一旦重载了运算符,那么,我们就可以让两个 Time 对象相加或相减。

Time t1 = Time();
Time t2 = Time();

Time t3 = t1 + t2;


友元函数

1.友元函数定义在类的外部,但有权访问 private,protected。
2.友元函数不是成员函数。
3.友元函数一般用于重载运算符,原型放在类声明中。  

利用成员函数重载运算符,比如 Time,Time对象在前面。

//允许
Time t1;
t1 + 123;

//不允许
123 + t1;

而利用友元就可以做到,比如创建如下友元函数。

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

这样就可以使用如下语句,利用 cout 打印 Time对象的内部数据。

Time t1;
cout << t1;

那如果要实现下面的这种使用方式,就需要有返回值了,因为它是从左往右依次结合。

cout << "Trip time: " << trip << " (Tuesday)\n";

//类似于下面,括号里返回的还是 cout 对象
(cout << "Trip time: ") << trip << " (Tuesday)\n";
((cout << "Trip time: ") << trip) << " (Tuesday)\n";
ostream & operator<<(ostream & os, const Time & t)
{
os << t.hours << " hours, " << t.minutes << " minutes";
return os;
}

例子

// mytime.h -- Time class with friends
#ifndef MYTIME3_H_
#define MYTIME3_H_
#include <iostream>

class Time
{
    private:
        int hours;
        int minutes;
    public:
        Time();
        Time(int h, int m = 0);
        void AddMin(int m);
        void AddHr(int h);
        void Reset(int h = 0, int m = 0);
        Time operator+(const Time & t) const;
        Time operator-(const Time & t) const;
        Time operator*(double n) const;
        friend Time operator*(double m, const Time & t)
        { return t * m; }   // inline definition
        friend std::ostream & operator<<(std::ostream & os, const Time & t);
};
#endif
// mytime.cpp
#include "mytime3.h"

Time::Time()
{
    hours = minutes = 0;
}

Time::Time(int h, int m)
{
    hours = h;
    minutes = m;
}

void Time::AddMin(int m)
{
    minutes += m;
    hours += minutes / 60;
    minutes %= 60;
}

void Time::AddHr(int h)
{
    hours += h;
}

void Time::Reset(int h, int m)
{
    hours = h;
    minutes = m;
}

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 Time & t) const
{
    Time diff;
    int tot1, tot2;
    tot1 = t.minutes + 60 * t.hours;
    tot2 = minutes + 60 * hours;
    diff.minutes = (tot2 - tot1) % 60;
    diff.hours = (tot2 - tot1) / 60;
    return diff;
}

Time Time::operator*(double mult) const
{
    Time result;
    long totalminutes = hours * mult * 60 + minutes * mult;
    result.hours = totalminutes / 60;
    result.minutes = totalminutes % 60;
    return result;
}

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

类的类型转换

假设我们有一个对象 Man。

Man m1;
//隐式类型转换,会调用构造函数。
m1 = 3;

构造函数可以是带一个参数的,也可以是带多个参数,但是后面的参数必须有默认值如

Man(int a);
Man(int a, int b=2);

也可以进行显式类型转换

m1 = Man(3);

//老式
m1 = (Man) 3;

但是当构造函数加上 explicit 限定词时,即关闭了隐式转换。

反过来,对象转成特定类型

比如要实现如下转换,要定义转换函数。

int a = m1;  //隐式

int a = int(m1);
int a = (int) m1;

转换函数必须注意以下几点

1.转换函数必须是类方法
2.转换函数不能指定返回类型
3.转换函数不能有参数

#ifndef STONEWT1_H_
#define STONEWT1_H_
class Stonewt
{
    private:
        ...
    public:
        ...
        operator int() const;
        operator double() const;
};
#endif
Stonewt::operator int() const
{
    return int (pounds + 0.5);
}

Stonewt::operator double() const
{
    return pounds;
}



©著作权归作者所有
收藏
推荐阅读
  • c++对象和类(1)-基础

    1.成员默认为private(只有类内部才能访问),protected(内部和子类能访问),public都能访问2.this指针指向对象本身,是对象的地址,this-&gt;height 代表对象本身...

  • c++函数,函数重载,函数模板

    函数重载函数重载的关键是函数的参数列表。如果两个函数的参数 数目和类型相同,同时参数的排列顺序也相同,则它们的特征标相同,而变量名是无关紧要的。C++允许 定义名称相同的函数,条件是它们的特征标不同。...

  • c++内存分配new、delete

    1.空指针使用delete是安全的。2.动态联编--运行时分配内存,灵活性高,性能略差。3.静态联编--编译时分配内存,灵活性差,性能高。//运行时分配 int * age = new int; de...

  • c++ string类、结构体

    string类的出现让c++相较于原生c处理字符串变的方便。char dog[4] = {'a', 'b', 'c', '\n'}; char dog[] = "abc";#include &lt;s...

  • c++基础知识

    包含头文件c++新式包含头文件的方式没有带 .h,这样就可以使用命名空间,虽然旧式可以写成 iostream.h,这样就不支持命名空间语法。#include &lt;iostream&gt; usi...

  • nginx模块 ngx_http_headers_module

    ngx_http_headers_module 模块是用来增加 Expires 和 Cache-control,或者是任意的响应头。Syntax: add_header name value [alw...

  • nginx模块 ngx_http_gunzip_module、ngx_http_gzip_module、ngx_http_gzip_static_module

    ngx_http_gunzip_module 模块将文件解压缩后并在响应头加上 "Content-Encoding: gzip" 返回给客户端。为了解决客户端不支持gzip压缩。编译的时候带上 --w...

  • nginx模块 ngx_http_flv_module、ngx_http_mp4_module

    ngx_http_flv_module模块提供了对 flv 视频的伪流支持。编译的时候带上 --with-http_flv_module。它会根据指定的 start 参数来指定跳过多少字节,并在返回数...

  • nginx模块 ngx_http_fastcgi_module

    ngx_http_fastcgi_module 模块使得nginx可以与 fastcgi 服务器通信。比如目前要使得 nginx 支持 php 就得使用 fastcgi技术,在服务器上装上 nginx...

  • nginx模块 ngx_http_autoindex_module

    ngx_http_autoindex_module 模块可以将uri以 / 结尾时,列出里面的文件和目录。Syntax: autoindex on | off; Default: autoindex ...

简介
天降大任于斯人也,必先苦其心志。