第1关:拷贝赋值运算符重载
任务描述
首先,赋值运算符重载必须使用成员函数形式。其次,拷贝赋值运算符是指形参为本类型的常引用的赋值运算符。也有直接以本类型为参数的拷贝赋值,但是不常见。通常拷贝赋值运算符重载的参数与拷贝构造函数保持一致。
相关知识
运算符重载,相当于一个固定了函数名的函数。以重载加号运算符为例,其函数名就是
operator +
运算符重载不能改变运算符的优先级与结合性,本质上也不能改变参数的数量(即双目运算符重载,必须拥有 2 个形参)。但是,如果以成员函数进行重载,则参数数量需要减一。减掉的那个参数,实际上就是调用该运算符时的类对象。
运算符重载的使用有 2 种形式,运算符形式和函数形式。以加号运算符为例,如果是成员函数形式重载,则:
Int a,b,c;
c = a + b;//运算符形式调用
c = a.operator + (b);//成员函数形式调用
如果是以普通函数形式重载,则:
Int a,b,c;
c = a + b;
c = operator + (a,b);
出于某种“对称性”的考虑,一般习惯使用普通函数来重载算术运算符。 事实上,如果你不进行拷贝赋值运算符重载,系统会主动为你添加一个拷贝赋值运算符重载,就如同拷贝构造函数、析构函数那样。
对这里的 Int
类而言,其实写不写拷贝赋值,都不影响程序的运行。不过还是要求按拷贝赋值运算符重载的标准范式进行书写。
编程要求
根据提示,在右侧编辑器的Begin-End区域内补充代码。
测试说明
本关有 2 个文件,main.cpp 和 Int.h,用户需要补齐 Int.h 内的相应内容。
main.cpp 的内容如下:
#include <iostream>
#include "Int.h"
using namespace std;
int main(){
Int a,b;
int x;
cin>>x;
a.setValue(x);
b = a;
cout<<b.getValue()<<endl;
return 0
-
/** * ?aê?ò???°ü×°àà(wrapper class)£?°ü×°àà?úC++?DóDμ?D?D?μ?ó?′|(?ù±?é???ó?)£??úJava?Dμ?ó?′|?ü′óò?D?£ */ #ifndef _INT_H_ //?aê?define guard #define _INT_H_ //?úCoíC++?D£?í·???t??ó|??óD?aí?òa class Int{ private://?aê?·??ê?????a?a??óDμ? int value; //?aê?êy?Y3é?±£??ò??3?Intê??ù±?ààDíintμ?°ü×°àà£??íê?òò?aIntà?????óDò???intààDíμ?êy?Y3é?± public: //?aê?1?óDμ? Int():value(0){} Int(Int const&rhs):value(rhs.value){} Int(int v):value(v){} int getValue()const{return value;} void setValue(int v){value=v;} //??±′?3?μ????·????? Int& operator = (const Int&rhs){ //?ú?aà?D′??ì?êμ??£?×¢òa×?×??ò?3?μμ??ì2a value=rhs.value; } };//??×??aà?óDò???·?o? #endif
任务描述
赋值运算符重载只能拥有一个形参。但是只要形参的类型不同,就能进行多个赋值运算符重载。这里重载一个以基本类型 int
为形参的赋值运算符。
相关知识
实际上,即使不重载这个运算符,相应的赋值操作也能进行。这是因为C++系统会尝试调用构造函数。
也就是说,如下代码
Int a;
a = 3;
如果你重载了以int为形参的赋值运算符,就相当于:
如果你没有重载该赋值运算符,则相当于:
编程要求
根据提示,在右侧编辑器的Begin-End区域内补充代码。
测试说明
如果你既没有重载该赋值运算符,也没有提供该构造函数,则上述程序是不能通过编译的。
本关有 2 个文件,main.cpp 和 Int.h,用户需要补齐 Int.h 内的相应内容。
main.cpp 的内容如下:
a.operator = (3);//3是一个int
a = Int(3);
#include <iostream>
#include "Int.h"
using namespace std;
int main(){
Int a;
int x;
cin>>x;
a = x;
cout<<a.getValue()<<endl;
return 0;
}
#include <iostream>
#include "Int.h"
using namespace std;
int main(){
Int a;
int x;
cin>>x;
a = x;
cout<<a.getValue()<<endl;
return 0;
}
/**
* ?aê?ò???°ü×°àà(wrapper class)£?°ü×°àà?úC++?DóDμ?D?D?μ?ó?′|(?ù±?é???ó?)£??úJava?Dμ?ó?′|?ü′óò?D?£
*/
#ifndef _INT_H_ //?aê?define guard
#define _INT_H_ //?úCoíC++?D£?í·???t??ó|??óD?aí?òa
class Int{
private://?aê?·??ê?????a?a??óDμ?
int value; //?aê?êy?Y3é?±£??ò??3?Intê??ù±?ààDíintμ?°ü×°àà£??íê?òò?aIntà?????óDò???intààDíμ?êy?Y3é?±
public: //?aê?1?óDμ?
Int():value(0){}
Int(Int const&rhs):value(rhs.value){}
int getValue()const{return value;}
void setValue(int v){value=v;}
//?????3?μ????·?????
Int& operator = (int rhs){
//?ú?aà?D′??ì?êμ??
this->value=rhs;
}
};//??×??aà?óDò???·?o?
#endif
第3关:算术复合赋值符运算符重载
任务描述
一个令人惊讶的事实是复合赋值符运算符既能以成员函数进行重载,也能以普通函数进行重载。但是建议大家以成员函数的形式进行重载。
相关知识
这里,仅重载算术复合赋值运算符。另一个建议是,如果你重载了赋值运算符,又重载了算术运算符,你应该考虑重载算术复合赋值运算符。
编程要求
根据提示,在右侧编辑器的Begin-End区域内补充代码。
测试说明
本关有 2 个文件,main.cpp 和 Int.h,用户需要补齐 Int.h 内的相应内容。
main.cpp 的内容如下:
#include <iostream>
#include "Int.h"
using namespace std;
int main(){
int x,y;
cin>>x>>y;
Int a(x),b(y);
a += b;
cout<<a.getValue()<<" "<<b.getValue()<<endl;
return 0;
}
/** * ?aê?ò???°ü×°àà(wrapper class)£?°ü×°àà?úC++?DóDμ?D?D?μ?ó?′|(?ù±?é???ó?)£??úJava?Dμ?ó?′|?ü′óò?D??£ */ #ifndef _INT_H_ //?aê?define guard #define _INT_H_ //?úCoíC++?D£?í·???t??ó|??óD?aí?òa class Int{ private://?aê?·??ê?????a?a??óDμ? int value; //?aê?êy?Y3é?±£??ò??3?Intê??ù±?ààDíintμ?°ü×°àà£??íê?òò?aIntà?????óDò???intààDíμ?êy?Y3é?± public: //?aê?1?óDμ? Int():value(0){} Int(Int const&rhs):value(rhs.value){} Int(int v):value(v){} int getValue()const{return value;} void setValue(int v){value=v;} //??ê??′o??3?μ????·?????·????? Int& operator += (const Int&rhs){ //?ú?aà?êμ????ê??′o??3?μ????·? value=value+rhs.value; } };//??×??aà?óDò???·?o? #endif
第4关:复用算术运算符重载复合赋值运算符
任务描述
写一个完整的包含赋值运算符、算术运算符以及复合赋值运算符的重载代码。并且使用函数复用技术。
相关知识
按照学习的顺序,假定首先实现了赋值运算符以及算术运算符,现在要求利用前二者来实现复合赋值运算符。
此处插一句,这样写并不完美,真正好的做法是利用复合赋值运算符来实现算术运算符,就像下一关那样。原因是出于效率,大家可以自行对比本关与下一关可能的效率上的区别。
编程要求
根据提示,在右侧编辑器的Begin-End区域内补充代码。
测试说明
本关有 3 个文件,main.cpp 和 Int.h 以及 Int.cpp,用户需要书写 Int.cpp 内的相应内容。
main.cpp 的内容如下:
#include <iostream>
#include "Int.h"
using namespace std;
int main(){
int x,y;
cin>>x>>y;
Int a(x),b(y);
a += b;
cout<<a.getValue()<<" "<<b.getValue()<<endl;
return 0;
}
Int.h 文件的内容如下
/**
* 这是一个包装类(wrapper class),包装类在C++中有点小小的用处(基本上没用),在Java中的用处更大一些。
*/
#ifndef _INT_H_ //这是define guard
#define _INT_H_ //在C和C++中,头文件都应该有这玩意
class Int{
private://这是访问控制——私有的
int value; //这是数据成员,我们称Int是基本类型int的包装类,就是因为Int里面只有一个int类型的数据成员
public: //这是公有的
Int():value(0){}
Int(Int const&rhs):value(rhs.value){}
Int(int v):value(v){}
int getValue()const{return value;}
void setValue(int v){value=v;}
//拷贝赋值运算符重载
Int& operator = (const Int&rhs);
//算术复合赋值运算符声明
Int& operator += (const Int&rhs);
};//记住这里有一个分号
//算术运算符声明
Int operator + (const Int&lhs,const Int&rhs);
#endif
/********** BEGIN **********/ #include"Int.h" Int& Int::operator=(const Int&rhs) { this->setValue(rhs.getValue()); return *this; } Int& Int::operator+=(const Int&rhs) { this->setValue(this->getValue()+rhs.getValue()); return *this; } Int operator+(const Int&lhs,const Int&rhs) { Int m; m.setValue(lhs.getValue()+rhs.getValue()); return m; } /********** END **********/
第5关:复用复合赋值运算符重载算术运算符
任务描述
如果你不觉得啰嗦,或者你有程序员型强迫症的话,这里是一个完美的赋值运算符、算术运算符与复合赋值运算符的重载。
相关知识
首先重载赋值运算符与算术复合赋值运算符,然后利用前二者实现算术运算符重载。
编程要求
根据提示,在右侧编辑器的Begin-End区域内补充代码。
测试说明
本关有 3 个文件,main.cpp 和 Int.h 以及 Int.cpp,用户需要书写 Int.cpp 内的相应内容。
main.cpp 的内容如下:
#include <iostream>
#include "Int.h"
using namespace std;
int main(){
int x,y;
cin>>x>>y;
Int a(x),b(y);
a += b;
cout<<a.getValue()<<" "<<b.getValue()<<endl;
return 0;
}
Int.h 文件的内容如下
/**
* 这是一个包装类(wrapper class),包装类在C++中有点小小的用处(基本上没用),在Java中的用处更大一些。
*/
#ifndef _INT_H_ //这是define guard
#define _INT_H_ //在C和C++中,头文件都应该有这玩意
class Int{
private://这是访问控制——私有的
int value; //这是数据成员,我们称Int是基本类型int的包装类,就是因为Int里面只有一个int类型的数据成员
public: //这是公有的
Int():value(0){}
Int(Int const&rhs):value(rhs.value){}
Int(int v):value(v){}
int getValue()const{return value;}
void setValue(int v){value=v;}
//拷贝赋值运算符重载
Int& operator = (const Int&rhs);
//算术复合赋值运算符声明
Int& operator += (const Int&rhs);
};//记住这里有一个分号
//算术运算符声明
Int operator + (const Int&lhs,const Int&rhs);
#endif
/********** BEGIN **********/ #include"Int.h" Int& Int::operator=(const Int&rhs) { this->setValue(rhs.getValue()); return *this; } Int& Int::operator+=(const Int&rhs) { this->setValue(this->getValue()+rhs.getValue()); return *this; } Int operator+(const Int&lhs,const Int&rhs) { Int m; m+=lhs; m+=rhs; return m; } /********** END **********/