系部网站建设研究方案,电子印章在线制作生成器免费,微信企业网站html5模板,视频营销C核心编程——运算符重载 运算符重载的方法运算符重载函数作成员函数与友元函数重载双目运算符重载单目运算符重载流插入运算符和和流提取运算符重载流插入运算符和流提取运算符 运算符重载的… C核心编程——运算符重载 运算符重载的方法运算符重载函数作成员函数与友元函数重载双目运算符重载单目运算符重载流插入运算符和和流提取运算符重载流插入运算符和流提取运算符 运算符重载的方法
运算符重载的方法是定义一个重载运算符的函数使指定运算符不能能实现原有的功能还能实现在函数中指定新的功能。运算符重载的实质是函数的重载。 重载运算符的函数一般格式如下 函数类型 operator 运算符名称形参表 { 对运算符的重载处理 } 典例对运算符 “” 实现重载使之能用于两个复数相加。
#include iostream
using namespace std;
class Complex{
public:Complex(){real0;imag0;}//自定义有参构造 无参构造不再提供若要用需要自定义 Complex(int, int);Complex operator(Complex c);void display();private:int real;int imag;
};Complex::Complex(int real, int imag)
{this-real real;this-imag imag;
}Complex Complex::operator(Complex c)
{Complex tempc;tempc.real real c.real;tempc.imag imag c.imag;return tempc;
}
void Complex::display()
{cout ( real , imag i) endl;
}
int main()
{Complex c1(3,4);Complex c2(5,-10);Complex c3;c3 c1 c2; //相当于c3 c1.operator(c2); cout c1; c1.display();cout c2; c2.display();cout c1c2; c3.display();return 0;
} 说明
自定义有参构造函数则无参构造不再提供若要用需要重新自定义程序 c3 c1 c2 相当于 c3 c1.operator(c2); 使用运算符重载能使用户程序易于编写阅读和维护。
运算符重载函数作成员函数与友元函数 如果将运算符重载函数作为成员函数它可以通过this指针自由地访问本类的数据成员因此可以少写一个函数的参数。 但必须要求运算表达式(如c1c2)中第1个参数即运算符左侧的操作数)是一个类对象而且与运算符函数的类型相同。因为必须通过类的对象去调用该类的成员函数,而且只有运算符重载函数返回值与该对象同类型,运算结果才有意义。
如果想要计算复数整数如c1i需要重新重载运算符Complex Complex::operator(int i)
{Complex tempc;tempc.real real i;tempc.imag imag;return tempc;
}如果想要计算整数复数如ic1 则第一个参数不是类对象必须使用友元函数重载运算符。Complex operator(int i, Complex c)
{Complex tempc;tempc.real i c.real;tempc.imag c.imag;return tempc;
}一般将双目运算符重载为友元函数Complex operator(Complex c1, Complex c2)
{Complex tempc;tempc.real c1.real c2.real;tempc.imag c1.imag c2.imag;return tempc;
}从原则上讲要尽量将重载运算符函数作为成员函数但还因考虑其他各方因素和习惯以下方式可供参考 1C规定赋值运算符“”、下标运算符“[]”、函数调用运算符“()”、成员运算符“-”、必须作为成员函数重载。 2流插人“”和流提取运算符“”类型转换运算符函数不能定义为类的成员函数只能作为友元函数。 3一般将单目运算符和复合运算符( -/*!^%)重载为成员函数。 4一般将双目运算符重载为友元函数
完整代码可供参考
#include iostream
using namespace std;
class Complex{
public:Complex(){real0;imag0;}Complex(int, int);Complex::operator(int i);friend operator(int i, Complex c);friend Complex operator(Complex c1, Complex c2);void display();private:int real;int imag;
};//构造函数
Complex::Complex(int real, int imag)
{this-real real;this-imag imag;
}//复数整数
Complex Complex::operator(int i)
{Complex tempc;tempc.real real i;tempc.imag imag;return tempc;
}//整数 复数
Complex operator(int i, Complex c)
{Complex tempc;tempc.real i c.real;tempc.imag c.imag;return tempc;
}
//复数复数 一般情况下双目运算符重载为友元函数
Complex operator(Complex c1, Complex c2)
{Complex tempc;tempc.real c1.real c2.real;tempc.imag c1.imag c2.imag;return tempc;
}void Complex::display()
{cout ( real , imag i) endl;
}int main()
{Complex c1(3,4);Complex c2(5,-10);Complex c3,c4,c5;c3 c1 c2; //相当于c3 c1.operator(c2); c4 c1 4;c5 5 c2;cout c1; c1.display();cout c2; c2.display();cout c1c2; c3.display();cout c14; c4.display();cout 5c2; c5.display();return 0;
} 重载双目运算符
双目运算符是C中最常见的运算符双目运算符有两个操作数通常在运算符的左右侧重载函数应该有两个参数也通常设置为友元函数作为运算符重载函数。 典例声明一个字符串类String用来存放不定长的字符串重载运算符“”和“”用于两个字符串的等于、小于和大于的比较运算。 为了程序的设计了与便于理解程序设计分步骤编写。 1. 先建立一个String类
#include iostream
#include string.husing namespace std;
class String{
public://构造及打印函数 String(){pNULL;} //无参构造 String(char *str){pstr;} //有参构造 void display(){cout p endl;} //打印字符串
private:char *p;
};int main()
{//测试代码 String str1(Hello),str2(world);str1.display();str2.display();return 0;
} 2. 重载运算符 通过全局函数作类友元的方式重载运算符其重载函数实现体如下所示。
bool operator(String str1, String str2)
{if(strcmp(str1.p,str2.p)0)return true;elsereturn false;
}这只是一个并不很完善的程序但是已经完成实质性的工作了运算符重载成功了。既然对运算符“”的重载成功了其他两个运算符的重载如法炮制即可 3. 重载其他运算符 重载运算符“” 重载运算符
bool operator(String str1, String str2)
{if(strcmp(str1.p,str2.p)0)return true;elsereturn false;
}重载运算符“” //重载运算符
bool operator(String str1, String str2)
{if(strcmp(str1.p,str2.p)0)return true;elsereturn false;
}同时记得将上述三个重载函数声明为类的友元函数 //运算符重载函数
friend bool operator(String str1, String str2);
friend bool operator(String str1, String str2);
friend bool operator(String str1, String str2); 测试代码 int main()
{//测试代码 String str1(Hello),str2(world);cout (str1str2) endl; cout (str1str2) endl; cout (str1str2) endl; return 0;
} 测试结果 0 1 0
4. 修饰完善优化输出
//封装比较函数 优化输出
void compare(String str1, String str2)
{if((str1 str2)1){str1.display(); cout ; str2.display();}else if ((str1 str2)1){str1.display(); cout ; str2.display(); } else{str1.display(); cout ; str2.display();}
}增加了一个compare函数用来对两个字符串进行比较并输出相应的信息。这样可以减轻主函数的负担同时使主函数简明易读。 先搭框架、逐步扩充、由简到繁、最后完善。边编程、边调试、边扩充。 完整参考程序
#include iostream
#include string.husing namespace std;
class String{
public://构造及打印函数 String(){pNULL;} //无参构造 String(char *str){pstr;} //有参构造 void display(){cout p;} //打印字符串//运算符重载函数 friend bool operator(String str1, String str2);friend bool operator(String str1, String str2); friend bool operator(String str1, String str2); private:char *p;
};void compare(String str1, String str2)
{if((str1 str2)1){str1.display(); cout ; str2.display();}else if ((str1 str2)1){str1.display(); cout ; str2.display(); } else{str1.display(); cout ; str2.display();}
}int main()
{//测试代码 String str1(hello),str2(world);compare(str1,str2);return 0;
} //重载运算符
bool operator(String str1, String str2)
{if(strcmp(str1.p,str2.p)0)return true;elsereturn false;
}重载运算符
bool operator(String str1, String str2)
{if(strcmp(str1.p,str2.p)0)return true;elsereturn false;
}//重载运算符
bool operator(String str1, String str2)
{if(strcmp(str1.p,str2.p)0)return true;elsereturn false;
}重载单目运算符
重载单目运算符与重载双目运算符相似但由于单目运算符只有一个操作数因此单目运算符重载函数只有一个参数如果运算符重载函数作为成员函数则还可省略此参数。
典例以自增运算符为例设计一个Time类含数据成员minute(分)和sec(秒)模拟秒表每次走1秒满60秒进1分钟此时秒又从0起算。要求输出分和秒的值。
#include iostream
#include string.husing namespace std;
class Time{
public://构造及打印函数 Time(){min0;sec0;}Time(int,int);void display();//运算符重载Time operator();private:int min;int sec;
};//构造函数
Time::Time(int min, int sec)
{this-min min;this-sec sec;
}
//运算符重载
Time Time::operator()
{sec;if(sec60){min;sec0;}return *this;
}
//打印时间
void Time::display()
{cout min : sec endl;
}int main()
{int i;Time time1(34,12);for(i0;i61;i){time1;time1.display();}return 0;
} 程序对运算符“”进行了重载使它能用于Time类对象。 但问题是“”和“–”运算符有两种使用方式前置自增运算符和后置自增运算符它们的作用是不一样的在重载时怎样区别这二者呢? 针对“”和“–”这一特点C约定在自增(自减)运算符重载函数中增加一个int型形参就是后置自增(自减)运算符函数。 在上述程序的基础上增加对后置自增运算符的重载。
运算符重载后置 重载函数//运算符重载 后置
Time Time::operator(int)
{//建立临时对象 temp 并读取当前值 Time temp(*this); sec;if(sec60){min;sec0;}return temp;
}主函数程序程序int main()
{int i;Time time1(34,12);Time time2;time2time1;cout time2tim1: time1; time1.display(); cout time2; time2.display();return 0;
} 重载后置自增运算符时多了一个int型的参数增加这个参数只是为了与前置自增运算符重载函数有所区别此外没有任何作用。在定义函数时也不必使用此参数因此可省写参数名只须在括号中写int 即可。
重载流插入运算符和“和流提取运算符”
如果想用输出和输入自已声明的类型的数据必须对它们重载。 对“和”重载的函数形式如下 ostream operator(ostream , 自定义类 ) istream operator(istream , 自定义类 ) 重载“”和“”的函数只能作为友元函数不能将他们定义为成员函数
重载流插入运算符和
典例在上述代码的基础上重载输出运算符“”输出复数
#include iostream
#include string.husing namespace std;
class Complex{
public://构造及打印函数 Complex(){real0;imag0;} //无参构造 Complex(double i,double j){reali;imagj;} //有参构造 Complex operator(Complex ); //号运算符重载 friend ostream operator(ostream output, Complex c); //重载coutprivate:double real;double imag;
};Complex Complex::operator(Complex c)
{Complex temp;temp.real real c.real;temp.imag imag c.imag;return temp;
} ostream operator(ostream output, Complex c)
{output ( c.real , c.imag i);return output;
}int main()
{//测试代码 Complex c1(1.2, 2.3);Complex c2(0.8, 2.7);Complex c3;c3 c1 c2;cout c1 c2 c3;return 0;
}程序中重载了运算符“”运算符重载函数“operator”中的形参output是ostream类对象的引用形参名output是用户任意起的。 运算符“”的左面是cout前面已提到cout是在头文件iostream中声明的ostream类对象。“”的右面是c3,它是Complex类对象。由于已将运算符“”的重载函数声明为Complex类的友元函数编译系统把coutc3解释为 operator(cout, c1) 即以cout和c1作为实参调用下面的“operator”函数:
ostream operator(ostream output, Complex c)
{output ( c.real c.imag i);return output;
}调用函数时形参output成为实参cout的引用形参c成为c1的引用。因此调用函数的过程相当于执行
cout ( c1.real , c1.imag i);return output的作用 连续向输出流插入信息output是ostream类的对象的引用因此return output就是return cout.
流提取运算符
运算符重载函数istream operator(istream input, Complex c)
{input c.real c.imag;return input;
}函数的返回值仍然为输入流的引用第一个参数为输入流的引用第二个参数为复数的引用当调用以下函数时第一个参数被赋值为cin的引用第二个参数被赋值为c1的引用程序就相当于执行cin c1.real c1.imag执行完毕后返回istream的引用使得能够继续连续输入c2.函数的调用cin c1 c2; //其中c1c2代表2个复数