为什么要把友元和运算符重载放在一起讲? 因为运算符重载主要是针对类,所以会涉及到很多被保护和私有的成员数据获取。如果不借助友元,实现会很复杂。而使用了友元技术能够直接访问到被保护或者私有的成员数据让运算符重载操作变得更简单。
1 友元
1.1 友元可以干什么?
友元可以访问类内被保护或者私有的成员和方法。
1.2友元的分类
1.2.1 友元函数
1、友元函数声明的时候在不受类权限影响,即在public、private、protected权限下效果相同 2、友元函数在类中声明需要加上friend
Cow.h
#pragma once
#include<string>
using namespace std;
class Cow {
public:
Cow();
~Cow();
friend int getCowWeigth(const Cow& other);
private:
int weigth;
string sex;
};
Cow.cpp
#include "Cow.h"
Cow::Cow() {
this->weigth = 12;
string sex = "母牛";
}
Cow::~Cow() {
}
main.cpp
#include<iostream>
#include"Cow.h"
int getCowWeigth(const Cow& other) {
return other.weigth;
}
int main() {
Cow cow1;
cout << getCowWeigth(cow1) << endl;
return 0;
}
结果:
12
1.2.2 类成员函数作为友元
类成员函数作为友元该成员函数可以访问类中的私有属性 Cow.h
#pragma once
#include<string>
#include "Search.h"
using namespace std;
class Cow {
public:
Cow();
~Cow();
friend int Search::s1(const Cow& other);
private:
int weigth;
string sex;
};
Cow.cpp
#include "Cow.h"
Cow::Cow() {
this->weigth = 12;
string sex = "母牛";
}
Cow::~Cow() {
}
Search.h
#pragma once
class Cow;
class Search {
public:
Search();
~Search();
int s1(const Cow& other);
private:
};
Search.cpp
#include "Search.h"
#include "Cow.h"
Search::Search() {
}
Search::~Search() {
}
int Search::s1(const Cow& other) {
return other.weigth;
}
main.cpp
#include<iostream>
#include "Cow.h"
#include "Search.h"
int main() {
Cow cow1;
Search s1;
cout << s1.s1(cow1) << endl;
return 0;
}
结果:
12
1.2.3 友元类
友元类:友元类中所有成员函数都可以访问这个类的私有属性
Cow.h
#pragma once
#include<string>
using namespace std;
class Cow {
public:
Cow();
~Cow();
friend class Search;
private:
int weigth;
string sex;
};
Cow.cpp
#include "Cow.h"
Cow::Cow() {
this->weigth = 12;
string sex = "母牛";
}
Cow::~Cow() {
}
Search.h
#pragma once
class Cow;
class Search {
public:
Search();
~Search();
int s1(const Cow& other);
void s2(Cow& other);
private:
};
Search.cpp
#include "Search.h"
#include "Cow.h"
Search::Search() {
}
Search::~Search() {
}
int Search::s1(const Cow& other) {
return other.weigth;
}
void Search::s2(Cow& other) {
other.weigth = 13;
}
main.cpp
#include<iostream>
#include "Cow.h"
#include "Search.h"
int main() {
Cow cow1;
Search s1;
cout << s1.s1(cow1) << endl;
s1.s2(cow1);
cout << s1.s1(cow1) << endl;
return 0;
}
结果:
12
13
2 运算符重载
2.1 运算符重载中友元函数与友元类的区别
1、使用友元类只有一个参数,还有一个参数是对象本身省略,更符合封装要求。 但是无法实现普通类型+类这种,只能实现类+普通类型 2、使用友元全局函数更直观(参数两个),方便实现a+b,b+a这种。但是不利于封装。
2.2 运算符重载注意事项
2.3 重载+、-算数运算符
实现一头猪+一头羊=猪肉多少斤 如果同时用了友元函数和类成员函数做友元要注意调用冲突问题,一般用一种方法实现即可。 这里我使用两种方法演示,,后面为了偷懒我会使用某一种。
2.3.1 类成员函数做友元
原理:类1.operator运算符(类2/其他);
Pig.h
#pragma once
#include<string>
using namespace std;
class Sheep;
class Pig {
public:
Pig(int weight);
~Pig();
string operator+(const Sheep& other);
private:
int weight;
};
Pig.cpp
#include<sstream>
#include "Pig.h"
#include "Sheep.h"
Pig::Pig(int weight) {
this->weight = weight;
}
Pig::~Pig() {
}
string Pig::operator+(const Sheep& other) {
stringstream ret;
ret << "猪+羊=" << other.weight * 5 + this->weight << "斤猪肉";
return ret.str();
}
Sheep.h
#pragma once
#include"Pig.h"
class Sheep {
public:
Sheep(int weight);
~Sheep();
friend string Pig::operator+(const Sheep& other);
private:
int weight;
};
Sheep.cpp
#include "Sheep.h"
Sheep::Sheep(int weight) {
this->weight = weight;
}
Sheep::~Sheep() {
}
main.cpp
#include<iostream>
#include "Pig.h"
#include "Sheep.h"
int main() {
Pig pig1(50);
Sheep sheep1(60);
cout << pig1 + sheep1 << endl;
return 0;
}
结果:
猪+羊=350斤猪肉
2.3.2 友元函数
Pig.h
#pragma once
#include<string>
using namespace std;
class Sheep;
class Pig {
public:
Pig(int weight);
~Pig();
friend string operator+(const Pig& pig, const Sheep& sheep);
friend string operator+(const Sheep& sheep, const Pig& pig);
private:
int weight;
};
Pig.cpp
#include<sstream>
#include "Pig.h"
Pig::Pig(int weight) {
this->weight = weight;
}
Pig::~Pig() {
}
Sheep.h
#pragma once
#include<string>
using namespace std;
class Pig;
class Sheep {
public:
Sheep(int weight);
~Sheep();
friend string operator+(const Pig& pig, const Sheep& sheep);
friend string operator+(const Sheep& sheep, const Pig& pig);
private:
int weight;
};
Sheep.cpp
#include "Sheep.h"
Sheep::Sheep(int weight) {
this->weight = weight;
}
Sheep::~Sheep() {
}
main.cpp
#include<iostream>
#include<string>
#include<sstream>
#include "Pig.h"
#include "Sheep.h"
using namespace std;
string operator+(const Pig& pig, const Sheep& sheep) {
stringstream ret;
ret << "猪+羊=" << sheep.weight * 5 + pig.weight << "斤猪肉";
return ret.str();
}
string operator+(const Sheep& sheep, const Pig& pig) {
stringstream ret;
ret << "猪+羊=" << sheep.weight * 5 + pig.weight << "斤猪肉";
return ret.str();
}
int main() {
Pig pig1(50);
Sheep sheep1(60);
cout << pig1 + sheep1 << endl;
cout << sheep1 + pig1<< endl;
return 0;
}
结果:
猪+羊=350斤猪肉
猪+羊=350斤猪肉
2.4 重载=赋值运算符
利用已经创建的对象来修改已经创建的对象,就是我们常说的赋值构造函数
Sheep.h
#pragma once
#include<string>
using namespace std;
class Pig;
class Sheep {
public:
Sheep(int weight);
~Sheep();
string Descrition()const;
Sheep& operator=(const Sheep& other);
private:
int weight;
};
Sheep.cpp
#include<sstream>
#include "Sheep.h"
Sheep::Sheep(int weight) {
this->weight = weight;
}
Sheep::~Sheep() {
}
string Sheep::Descrition()const {
stringstream ret;
ret << "weigtf:" << this->weight;
return ret.str();
}
Sheep& Sheep::operator=(const Sheep& other) {
if (this == &other) {
return *this;
}
this->weight = other.weight;
return *this;
}
main.cpp
#include<iostream>
#include "Sheep.h"
using namespace std;
int main() {
Sheep s1(12);
cout << s1.Descrition() << endl;
Sheep s2(13);
cout << s2.Descrition() << endl;
s1 = s2;
cout << s1.Descrition() << endl;
cout << s2.Descrition() << endl;
return 0;
}
结果:
weigtf:12
weigtf:13
weigtf:13
weigtf:13
2.5 重载<、>、==逻辑运算符
Sheep.h
#pragma once
#include<string>
using namespace std;
class Sheep {
public:
Sheep(int weight);
~Sheep();
string Descrition()const;
bool operator<(const Sheep& other);
private:
int weight;
};
Sheep.cpp
#include<sstream>
#include "Sheep.h"
Sheep::Sheep(int weight) {
this->weight = weight;
}
Sheep::~Sheep() {
}
string Sheep::Descrition()const {
stringstream ret;
ret << "weigtf:" << this->weight;
return ret.str();
}
bool Sheep::operator<(const Sheep& other) {
if (this->weight < other.weight) {
return true;
}
else {
return false;
}
}
main.cpp
#include<iostream>
#include "Sheep.h"
using namespace std;
int main() {
Sheep s1(12);
cout << s1.Descrition() << endl;
Sheep s2(13);
cout << s2.Descrition() << endl;
cout << (s1 < s2) << endl;
return 0;
}
结果:
weigtf:12
weigtf:13
1
2.6 重载[]下标运算符
Sheep.h
#pragma once
#include<string>
using namespace std;
typedef enum NUM {
one,
two,
tree
}Num_type;
class Sheep {
public:
Sheep(int weight);
~Sheep();
string Descrition()const;
int operator[](Num_type numtype);
private:
int weight;
};
Sheep.cpp
#include<sstream>
#include "Sheep.h"
Sheep::Sheep(int weight) {
this->weight = weight;
}
Sheep::~Sheep() {
}
string Sheep::Descrition()const {
stringstream ret;
ret << "weigtf:" << this->weight;
return ret.str();
}
int Sheep::operator[](Num_type numtype) {
switch (numtype) {
case one:
return 1;
case two:
return 2;
case tree:
return 3;
default:
return 0;
}
}
main.cpp
#include<iostream>
#include "Sheep.h"
using namespace std;
int main() {
Sheep s1(12);
cout << s1[two] << endl;
cout << s1[one] << endl;
return 0;
}
结果:
2
1
2.7 重载<<、>>输入输出运算符
可以输入或者输出对象特地内容。 最好使用友元函数,因为友元类和我们正常使用相反不好理解。
Sheep.h
#pragma once
#include<string>
using namespace std;
class Sheep {
public:
Sheep(int weight);
~Sheep();
friend ostream& operator<<(ostream& cout, const Sheep& shepp);
private:
int weight;
};
Sheep.cpp
#include<sstream>
#include "Sheep.h"
Sheep::Sheep(int weight) {
this->weight = weight;
}
Sheep::~Sheep() {
}
main.cpp
#include<iostream>
#include "Sheep.h"
using namespace std;
ostream& operator<<(ostream& cout, const Sheep& sheep) {
cout << sheep.weight;
return cout;
}
int main() {
Sheep s1(12);
cout << s1 << endl;
return 0;
}
结果:
12
2.8 重载类型运算符
2.8.1 普通类型->类类类型
如果在创建对象的时候使用普通类型赋值,实际上会调用类的自定义带参构造函数 原理: A a = 12; 实际会调用A(int)带参构造函数。
Sheep.h
#pragma once
class Sheep {
public:
Sheep(int weigth);
~Sheep();
int Describtion()const;
private:
int weigth;
};
____```
Sheep.cpp
```cpp
#include "Sheep.h"
Sheep::Sheep(int weigth) {
this->weigth = weigth;
}
Sheep::~Sheep() {
}
int Sheep::Describtion()const {
return weigth;
}
main.cpp
#include<iostream>
#include"Sheep.h"
using namespace std;
int main() {
Sheep s1 = 13;
cout << s1.Describtion() << endl;
return 0;
}
结果:
13
2.8.2 类类型A->类类型B
实现: B b; A a = b;
利用拷贝构造函数 A(const B& other);
Bigsheep.h
#pragma once
class Sheep;
class BigSheep {
public:
BigSheep(int weigth);
BigSheep(const Sheep& other);
~BigSheep();
int Describtion()const;
private:
int weigth;
};
Bigsheep.cpp
#include "BigSheep.h"
#include "Sheep.h"
BigSheep::BigSheep(int weigth) {
this->weigth = weigth;
}
BigSheep::~BigSheep() {
}
BigSheep::BigSheep(const Sheep& other) {
this->weigth = other.weigth;
}
int BigSheep::Describtion()const {
return weigth;
}
Sheep.h
#pragma once
class Sheep {
public:
Sheep(int weigth);
~Sheep();
int Describtion()const;
friend class BigSheep;
private:
int weigth;
};
Sheep.cpp
#include "Sheep.h"
Sheep::Sheep(int weigth) {
this->weigth = weigth;
}
Sheep::~Sheep() {
}
int Sheep::Describtion()const {
return weigth;
}
main.cpp
#include<iostream>
#include"Sheep.h"
#include "BigSheep.h"
using namespace std;
int main() {
Sheep s1 = 13;
BigSheep Bigsheep = s1;
cout << Bigsheep.Describtion() << endl;
return 0;
}
结果:
13
2.8.3 类类型->普通类型
类型运算符重载不要返回类型,添加会出错 operator int();
Sheep.h
#pragma once
class Sheep {
public:
Sheep(int weigth);
~Sheep();
int Describtion()const;
operator int() const;
private:
int weigth;
};
Sheep.cpp
#include "Sheep.h"
Sheep::Sheep(int weigth) {
this->weigth = weigth;
}
Sheep::~Sheep() {
}
int Sheep::Describtion()const {
return weigth;
}
Sheep::operator int() const {
return weigth;
}
main.cpp
#include<iostream>
#include"Sheep.h"
using namespace std;
int main() {
Sheep s1 = 13;
int num = s1;
cout << num << endl;
return 0;
}
结果:
13
后续完善
|