关闭

运算符重载里面程序运行细节

标签: 运算符重载输入输出流重载
138人阅读 评论(0) 收藏 举报
分类:

用一个Integer的类来模拟int数据类型的操作过程

首先实现运算符+的重载,来详细观察里面的执行流程。
在该类中写出了默认析构函数,默认拷贝函数,默认赋值函数。
重载了构造函数,operator= 函数,operator+ 和operator+的友元函数

在operator+中通过临时的类对象实现了加法而不会改变类成员变量原本的值,返回值必须是类的对象而不能是引用,返回类对象时会调用拷贝构造函数为该临时的对象创建一个副本,使得里面的数据不会失效。此方法可以实现一个类的对象demo+num的操作。如(demo+100)
同时写了一个operator+的友元函数,此函数并非类的成员函数,不能通过成员访问符访问到。它的主要作用是可以实现num + 类对象demo的操作。如(100+demo)

class Integer
{
public:
    Integer(int num = 0);
    ~Integer();
    Integer(const Integer& other);
    Integer &operator=(int num);
    Integer &operator=(Integer &other);
    friend Integer operator+(int num, Integer &me);
    Integer operator+(int num);
    int GetNum();
private:
    int _num;
};

类成员函数的实现

Integer::Integer(int num) :_num(num)
{
    std::cout << "Integer(int)" << _num  << std::endl;
}

Integer::~Integer()
{
    std::cout << "~Integer()" << std::endl;
}

Integer::Integer(const Integer & other)
{
    _num = other._num;
    std::cout << "Integer(Integer&)" << _num << std::endl;
}

Integer & Integer::operator=(int num)
{
    _num = num;
    std::cout << "operator=(int)" << _num <<std::endl;
    return *this;
}

Integer & Integer::operator=(Integer & other)
{
    _num = other._num;
    std::cout << "operator=(Integer&)" << _num << std::endl;
    return *this;
}

Integer Integer::operator+(int num)
{
    Integer temp = _num;
    temp._num += num;
    std::cout << "operator+(int)" << temp._num << std::endl;
    return temp;
}

int Integer::GetNum()
{
    return _num;
}

Integer operator+(int num, Integer & me)
{
    Integer temp = me._num;
    temp._num += num;
    std::cout << "operator+(friend&)" << temp._num << std::endl;
    return temp;
}

类的成员函数中会打印出一些字符来方便观察程序的执行流程

int main()
{
    Integer demo = 10, other ;
    other = 100 + demo + 200;
    return 0;
}

只是两步简单的调用,在类中运行的过程确实比较复杂的
函数的调用过程
程序首先会通过构造函数创建一个demo和一个other的类对象
执行到第二句话是,此时这个表达式的运算顺序是从左至右的。
此时程序会进入第一个加法函数,也就是operator+的友元函数。此时会通过构造函数创建一个类对象并将当前demo._num的值给该对象temp。在通过temp实现加法运算,因为该函数的返回值为类的对象,所以在返回时会调用拷贝构造函数,将temp的值拷贝一个副本,在函数结束后temp被析构。
然后程序会进入第二个加法函数,也就是重载的operator+函数。通上一个函数的执行方法。在该函数结束后,temp被析构,此时会将计算出来的结果,因为加法函数的返回值为类的对象,此时会通过默认的赋值函数将结果给到other中。
然后会将之前通过复制构造函数创建的副本对象析构掉。
最后,析构demo和other。
这便是这么简单一个运算的里面的执行流程。

将里面的other对象放在下面创建,此时里面的执行流程又会发生一些变化

int main()
{
    Integer demo = 10;
    Integer other = 100 + demo + 200;
    return 0;
}

执行流程的变化

从这里面可以很明显的看出,里面的析构少了一次。

按照c++基础知识里面的原理。

Integer other = 100 + demo + 100;

因为后面的计算结果为一个Integer的对象,此时的=并非赋值,它会调用复制构造函数。而两个operator+的函数在返回时也会调用复制构造函数。此时总共应该调用三次复制构造函数。在程序的执行过程中复制构造函数只有两次被调用了。

在我的理解中,在最后一个operator+函数执行完返回的时候调用了复制构造函数,此时为里面的临时对象创建了一个副本。而该副本就为other,此时直接将计算的结果给了other。所以other不会再被创建

理解了operator+的执行流程之后来看一下++的函数实现

Integer& operator++();
Integer operator++(int);

这两个函数分别代表的是前++与后++,无参数的为前++,有参数的为后++,里面的参数只是作为重载来用,并没有其他的实际用途

函数实现如下

Integer & Integer::operator++()
{
    _num += 1;
    return *this;
}

Integer Integer::operator++(int)
{
    Integer temp = *this;
    _num += 1;
    return temp;
}

假设定义了

int n1 = 10;
int n2 = n1++;

在第二句话执行完之后n1的值变为了11,此时n2的值为10.重载的后++函数通过返回一个临时对象的拷贝实现了这一操作。

我们还可以重载“<<”“>>”运算符来实现更加方便的输入与输出

friend std::ostream & operator<<(std::ostream & lhs, const Integer & rhs)
{
    lhs << rhs._num;
    return lhs;
}

friend std::istream& operator>>(std::istream &lhs, Integer &rhs)
{
    lhs >> rhs._num;
    return lhs;
}
0
0
查看评论

才知道java竟然没有运算符重载

写复数类的乘法和除法真的是要写死人了。。。public class Complex { private Fraction realPart; private Fraction imagePart; public Complex(Fraction real,Fraction ima...
  • liaotl10
  • liaotl10
  • 2017-07-11 22:16
  • 840

了解程序编译、运行过程

了解程序编译、运行过程计算机系统是由硬件和软件系统组成的,它们共同工作来运行应用程序。程序编译系统中所有的信息——包括磁盘文件、存储器中的程序、存储器中存放的用户数据以及网络上传送的数据,都是由一串位表示的。区分不同数据对象的唯一方法是读到这些数据对象时的上下文。如,在不同的上下文中,一个同样的字节...
  • yzhang6_10
  • yzhang6_10
  • 2016-07-29 23:08
  • 694

c加加+-*/前置++后置++运算符重载

运算符重载注意点: 1.算术和关系操作符返回的是一个左值或右值,而不是一个引用 2.赋值操作符一定要定义为成员函数如“=” 3.一般而言,赋值操作符和复合赋值操作符应返回左操作数的引用如"="和''+=" C++不允许赋值运算符被重载为全局形式,这是因为...
  • littleprince1
  • littleprince1
  • 2017-04-18 16:46
  • 804

C++_运算符重载_前缀自增与后缀自增

由于前缀自增与后缀自增在如果通过运算符重载在形式上相同,都为 以Date类为例 Date& operator++(Date &)(全局函数)/ Date& operator++( )(成员函数)无法区分。 故人为规定前缀自增与后缀自增运算符的表达形式: 由于编译器必...
  • u010003835
  • u010003835
  • 2015-08-06 18:16
  • 2752

关于运算符重载的两种方式的优缺点比较

大家都知道一般常用两种重载运算符的方式分别是: 1.作为成员函数重载运算符.    2.作为友元函数重载运算符. 这里我给个例子. 这里是DoubleA class DoubleA { public: DoubleA(){}; DoubleA(DoubleB m); ...
  • y1196645376
  • y1196645376
  • 2016-03-31 17:06
  • 2921

类的运算符重载

<br />类的运算符重载 <br />参考书籍 :C++ 世界的两本世界名著 [C++ 程序设计语言 ] 和 [C++primer]<br />重载知识点 <br />1. 重载运算符 <br />1.1 引言 <br />1...
  • smy0816
  • smy0816
  • 2011-05-06 19:15
  • 3732

运算符重载(一般、关系、逻辑、单目、箭头操作符)

c++的一大特性就是重载(overload),通过重载可以把功能相似的几个函数合为一个,使得程序更加简洁、高效。在c++中不止函数可以重载,运算符也可以重载。由于一般数据类型间的运算符没有重载的必要,所以运算符重载主要是面向对象之间的。1.一般运算符重载在进行对象之间的运算时,程序会调用与运算符相对...
  • duzejie
  • duzejie
  • 2016-10-07 18:23
  • 972

C++基础篇--运算符重载

运算符重载没有多高深复杂,但牵扯到的相关概念和语法变化不少,如果这块基石不牢固,读复杂C++代码时就只有雾里看花的份。 运算符重载由来     C/C++中所有运算符(+-*/等)默认只用于基本数据类型(int floatdouble等),而对自定义的struct/cl...
  • ipmux
  • ipmux
  • 2015-09-01 15:04
  • 974

关于c++的运算符重载那些事

搞c++有一段时间了,今天突然要重载一个运算符,发现自己有点忘了,遂查查资料做一下c++运算符重载的小总结。 一、何为运算符重载 运算符的重载是c++语言特有的,java什么的是没有运算符重载的,所以运算符重载在笔试面试中有可能成为c++的高频考点。运算符重载就是重新定义运算符的意义,如常用的+,-...
  • uestclr
  • uestclr
  • 2016-04-16 21:59
  • 3250

LintCode-赋值运算符重载

实现赋值运算符重载函数,确保: 新的数据可准确地被复制旧的数据可准确地删除/释放可进行 A = B = C 赋值 样例 如果进行 A = B 赋值,则 A 中的数据被删除,取而代之的是 B 中的数据。 如果进行 A = B =...
  • wangyuquanliuli
  • wangyuquanliuli
  • 2015-05-21 18:14
  • 1856
    个人资料
    • 访问:8561次
    • 积分:698
    • 等级:
    • 排名:千里之外
    • 原创:64篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章分类