在研究类的默认成员函数的时候我们接触到了运算符重载,其中包括赋值操作符重载 取地址操作符重载 const 修饰的取地址操作符的重载
这一节我们主要来研究一下赋值运算符以及·加加减减的重载
运算符的重载实际上是对运算符函数的重载来实现的
话不多说直接上代码来看
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class complex
{
private:
double real;
double imag;
public:
complex(double r = 0.0, double i = 0.0)
{
real = r;
imag = i;
}
void display();
complex operator +(const complex &c);//二元加重载成员函数
complex operator -(const complex &c);//二元减重载成员函数
complex operator - ();//一元重载成员函数
};
void complex::display()
{
cout << "real = " << real << endl;
cout << "imag = " << imag << endl;
}
complex complex::operator+(const complex &c)
{
double r = real + c.real;
double i = imag + c.imag;
return complex(r, i);
}
complex complex::operator-(const complex &c)
{
double r = real- c.real;
double i = imag - c.imag;
return complex(r, i);
}
complex complex::operator-()
{
return complex(-real, -imag);
}
int main()
{
complex a(1.5,52.2), b(2.3,63.2);
complex c = a + b;
complex d = -a;
d .display();
c.display();
system("pause");
return 0;
}
通过这段代码我们发现,通过对于运算符的重载可以实现对于类的想要操作,语法通过代码也就很明显的展现出来
函数类型 + operator + 重载的运算符(形参列表)
{
函数体;
}
重载类的成员函数的时候,参数个数 = 原操作数个数 -1(后置++,前置++除外);
当类的对象调用这种运算符函数的时候,对象中的成员数据就是一个操作数,另一个操作数通过参数传递来获得。
看完这 很多人应该想问为啥参数个数等于原来操作数减1?
this指针不知道你是否还记得?
当操作数为双目运算符的时候,其中一个运算数据是对象本身的数据,由this指针给出,另一个操作数的数据需要传参数来确定,(当然,特殊情况狂特殊考虑),运算符是单目运算符的时候,操作数直接由this指针给出,就不需要任何函数来传递。
类的友元函数的重载
运算符重载为类的友元函数时,所需要的操作数必须通过函数形参来传递。
上面我们刚提到了this指针,在学习友元的时候我们说友元函数没有this指针,所以参数传递就只有是形参来传递了。
也分为两种情况:
- 当运算符为双目运算符时,以加号为例 a+b 实际上就是 operator+(a,b);
- 当运算符为单目运算符的时候 比如后置减减,实际上就是调用函数operator–(a);
具体怎么样直接上代码看实际情况中的操作
class complex
{
private:
double real;
double imag;
public:
complex(double r = 0.0, double i = 0.0)
{
real = r;
imag = i;
}
void display();
friend complex operator-(const complex &c1, const complex &c2);//二元重载减友元函数
friend complex operator-(const complex &c);//一元重载减友元函数
friend complex operator+(const complex &c1, const complex &c2);//二元重载加友元函数
};
void complex::display()
{
cout << "real = " << real << endl;
cout << "imag = " << imag << endl;
}
complex operator-(const complex &c1, const complex &c2)
{
double r = c1.real - c2.real;
double i = c1.imag - c2.imag;
return complex(r, i);
}
complex operator-(const complex &c)
{
double r = -c.imag;
double i = -c.real;
return complex(r,i);
}
complex operator+(const complex &c1, const complex &c2)
{
double r = c1.real + c2.real;
double i = c1.imag + c2.imag;
return complex(r, i);
}
int main()
{
complex a(1.5, 52.2), b(2.3, 63.2);
complex c = a + b;
complex d = -a;
d.display();
c.display();
system("pause");
return 0;
}
我们可以发现,在友元函数重载的过程中,函数参数 = 原来操作数的个数,至少有一个自定义类型的形式参数,在调用这种运算符函数的时候,所有的操作数都要通过参数传递来获得。
友元函数不能重载的运算符
= ()-> 。
接下来就是我们学习C++过程中经常需要实现的多种运算符的重载:
一·. ++和–的重载
主要还是强调一下后置++ --的重载操作,前置操作在前面实现复数运算的时候已经实现,主要是后置时候的操作,我们需要增加一个int类型的参数,在调用时,参数Int并不参与运算,只是用来区分重载函数。
话不多说,直接上代码:
class test
{
private:
int t1, t2;
public:
test(int num1, int num2);
test operator++();//后置加加
test operator--();//后置减减
test operator++(int);//前置加加
test operator--(int);//前置减减
void display();
};
test::test(int num1, int num2)
{
t1 = num1;
t2 = num2;
}
test test::operator++()
{
++t1;
++t2;
return *this;
}
test test::operator--()
{
--t1;
--t2;
return *this;
}
void test::display()
{
cout << "t1 = " << t1 << endl;
cout << "t2 = " << t2 << endl;
}
test test::operator++(int)
{
int temp1 = t1;
int temp2 = t2;
t1++;
t2++;
return test(temp1,temp2);
}
test test::operator--(int)
{
int temp1 = t1;
int temp2 = t2;
t1--;
t2--;
return test(temp1, temp2);
}
再来看常用的 = 的重载
相信大家在看完加加减减的重载后对于=一定也有自己的想法吧,这个主要是但是我们需要注意几点:
- 有一个引用参数,为了防止对赋值号右边进行拷贝,从而提高函数运行时效率,
- 函数返回了引用而不是对象,这样,赋值构造函数不如使用引用参数和返回引用更加有效。
例如:
class String
{
private:
char* ptr;
public:
String( char* s)
{
ptr = new char[strlen(s) + 1];
strcpy(ptr, s);
}
~String()
{
delete ptr;
}
void print()
{
cout << ptr << endl;
}
String &operator = ( String & s);//函数返回引用更为有效
};
String &String::operator=(String &s )
{
if (this == &s)
{
return *this;
}
else {
delete ptr;
ptr = new char[strlen(s.ptr) + 1];
strcpy(ptr, s.ptr);
return *this;
}
}
int main()
{
char* str = (char*)"你好";
String p1(str);
char* str1 =(char*) "我美吗";
String p2(str1);
p1 = p2;
p1.print();
system("pause");
return 0;
}
这样就完成了赋值运算符的重载,其实根据类私有成员的不同,重载的方式是不同的,具体还要看怎么实现,掌握语法和原理很重要,在接下来的学习中一起看啊。