C++快速讲解(六):运算符重载和lambda表达式
前言:主要介绍了运算符重载和lambda的使用。
1.运算符简单使用
1.1 成员函数方式
把重载的运算符函数定义在类中,此时只需要接收一个参数,因为类的对象本身作为+ 的前面调用者。
实现自定义的加法:
#include <iostream>
//成员函数方式 把重载的运算符函数定义在类中,此时只需要接收一个参数,因为类的对象本身作为+ 的前面调用者。
using namespace std;
class DiyAdd{
public:
int number;
DiyAdd(int number):number{number}{
cout<<"构造函数"<<endl;
}
//自定义两个数字之和
//方便在外面接收
DiyAdd operator+ (DiyAdd &n){
DiyAdd temp(this->number+n.number);
return temp;
}
};
int main() {
DiyAdd d1(10);
DiyAdd d2(20);
DiyAdd d3 = d1+d2;
cout<<"d3:"<<d3.number<<endl;
return 0;
}
1.2 全局函数方式
并不是所有的运算符重载都能定义在类中,比如,需要扩展一些已有的类,对它进行运算符重载,而这些类已经被打成了一个库来使用,此时通过全局函数的方式来实现运算符重载。
#include <iostream>
#include <string>
//全局函数方式
using namespace std;
class DiyAdd{
public:
int number;
DiyAdd(int number):number(number){
cout<<"function"<<endl;
}
};
//由于函数并非定义在类中,所以此处无法使用到this指针,则需要传递两个对象进来。
DiyAdd operator+ (DiyAdd &d , DiyAdd &dd ){
DiyAdd temp(d.number + dd.number);
return temp;
}
int main() {
DiyAdd d1(20);
DiyAdd d2(30);
//这里等于使用s1的对象,调用了operator+这个函数, +后面的 s2 则被当成参数来传递
DiyAdd d3 = d1 + d2;
cout << "d3.number = " << d3.number << endl;
return 0;
}
2.输出运算符重载
#include <iostream>
#include <string>
//输出运算符重载
using namespace std;
class Student{
public:
string name = "zhangsan";
Student(string name){
this->name = name;
}
};
//对 << 运算符进行重载。 这里使用的是全局函数 ,第一个参数ostream 是因为在外面调用<<这个运算符的时候,cout 在前,cout 为ostream这种类型的对象。
ostream & operator<< (ostream& o,Student &s1){
o << s1.name;
return o;
}
int main() {
Student s1("fly");
cout << s1 << endl;
return 0;
}
3.输入运算符重载
#include <iostream>
#include <string>
//输入运算符重载
using namespace std;
class Student{
public:
string name;
};
//对 << 运算符进行重载。
ostream& operator<< (ostream& o, Student &s1){
o << s1.name ;
return o;
}
//对 >> 运算符进行重载
istream& operator>> (istream& in, Student &s1){
in >> s1.name;
return in;
}
int main() {
Student s1;
cout << "请输入学生的姓名:" << endl;
cin >> s1;
//打印学生, 实际上是打印他的名字。
cout << s1 <<endl ;
return 0;
}
4.赋值运算符重载
4.1 拷贝赋值运算
#include <iostream>
#include <string>
//拷贝赋值运算
using namespace std;
class Student{
string name;
public:
Student(string name):name(name){
cout<<"function"<<endl;
}
//拷贝赋值
void operator=(const Student &s){
name = s.name;//浅拷贝
// name = new string(*s.name);//深拷贝
};
void run(){
cout<<name<<endl;
}
};
int main() {
Student s1("fly");
Student s2("zhangsan");
s1 = s2;
s1.run();
s2.run();
return 0;
}
4.2 移动赋值运算
#include <iostream>
#include <string>
using namespace std;
class Student{
string *pad_name;
public:
Student(string pad_name):pad_name(new string(pad_name)){
cout<<"function"<<endl;
}
//拷贝赋值
void operator=(const Student &s){
pad_name = s.pad_name;//浅拷贝
// name = new string(*s.name);//深拷贝
};
//移动赋值运算符号
void operator = (Student&&s){
delete pad_name;//先自己放弃自己的空间
pad_name = s.pad_name;//让现在的对象指向源对象空间
s.pad_name = nullptr;//让把源对象的空间所有权减掉
}
void run(){
cout<<*pad_name<<endl;
}
};
int main() {
Student s1("aa");
Student s2("bb");
s1 = move(s2);
s1.run();
s2.run();
return 0;
}
5.调用运算符重载
#include <iostream>
using namespace std;
class Calc{
public:
int operator()(int val){
return val <0 ? -val :val;
}
};
int main(){
Calc c ;
int value = c(-10);
cout<<value<<endl;
return 0;
}
6.lambda表达式的语法
在编写lambda表达式的时候,可以忽略参数列表和返回值类型,但是前后的捕获列表和函数体必须包含 , 捕获列表的中括号不能省略,编译根据它来识别后面是否是lambda表达式 ,并且它还有一个作用是能够让lambda的函数体访问它所处作用域的成员。
#include <iostream>
#include <string>
using namespace std;
int main() {
//示例1:
[](int a ,int b)->int{return a + b ;} ; //一个简单的加法
//例子2 如果编译器能推断出来类型。,那么 ->int 也可以省略掉
[](int a ,int b){return a + b ;} ;
//如果不需要参数,那么参数列表页可以忽略。至此不能再精简了。
[]{return 3 + 5 ;};
//1.接收lambda表达式,然后调用
auto f = [](int m,int n)->int {return m+n;};
//2.调用lambda表达式
int result = f(3,4);
cout<<result<<endl;
//不接受表达式,直接调用
int result2 = [](int m,int n){return m-n;}(10,2);
cout<<result2<<endl;
return 0;
}
7.lambda的捕获列表的使用
#include <iostream>
#include <string>
//捕获列表的使用
using namespace std;
int main() {
int m = 10;
int n = 20;
//值传递方式捕获 m 和 n , 在lanmbda 表示内部无法修改m和n的值
auto f1 = [m,n]{return m + n;};
cout << f1() << endl; //打印 8
//引用方式捕获 m 和 n , 可以在内部修改m 和 n的值
auto f2 = [&m,&n]{
m = 99; //这里修改会导致外部的m 也跟着修改。
return m + n;
};
cout << f2() << endl; //这里打印35
cout << "m= "<< m << endl; //再打印一次,m 变成30了
return 0;
}
8.labmda应用
编写lamdda表达式很简单,但是用得上lambda表达式的地方比较特殊。一般会使用它来封装一些逻辑代码,使其不仅具有函数的包装性,也具有可见的自说明性。有点类似于java里面的匿名内部类。
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> scores = {80,90,100,22,33,55};
int result2 = [&]{
int result = 0;
for (int s: scores){
result += s;
}
return result;
}();
cout<<result2<<endl;
return 0;
}
结束!!!