用一个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;
}