目录
友元
让一个函数或者类访问另一个类中私有成员
关键字:friend
三种实现:
1 全局函数做友元
使用全局函数访问类中的私有成员
friend void goodGay(Building* building);
#include <iostream>
using namespace std;
#include<string>
class Building
{
//goodGay全局函数是Building的友元函数,可以访问私有成员
friend void goodGay(Building* building);
public:
Building()
{
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
public:
string m_SittingRoom; // 客厅
private:
string m_BedRoom; // 卧室
};
//全局函数
void goodGay(Building * building)
{
cout << "好朋友全局函数正在访问:" << building->m_SittingRoom << endl;
cout << "好朋友全局函数正在访问:" << building->m_BedRoom << endl;
}
void test01() {
Building building;
goodGay(&building);
}
int main() {
test01();
system("pause");
return 0;
}
2 类做友元
friend class GoodGay;
代码中包括类中构造函数以及成员函数的类外实现(加::作用域)
#include <iostream>
using namespace std;
#include<string>
// 类做友元
class Building; //提前声明
class GoodGay {
public:
GoodGay();
void visit();//参观函数 访问building中属性
Building* building;
};
class Building
{
//友元类,可以访问私有成员
friend class GoodGay;
public:
Building(); //构造函数,本次放在类外实现
public:
string m_SittingRoom; // 客厅
private:
string m_BedRoom; // 卧室
};
Building::Building()
{
m_SittingRoom = "客厅";
m_BedRoom="卧室";
}
GoodGay::GoodGay() {
//创建建筑物对象
building = new Building; //在堆区创建一个对象,用building维护
}
void GoodGay::visit() {
// 类外实现GoodGay类中的函数
cout << "GoodGay类正在访问:" << building->m_SittingRoom << endl;
cout << "GoodGay类正在访问:" << building->m_BedRoom << endl;
}
void test01() {
GoodGay g;
g.visit();
}
int main() {
test01();
system("pause");
return 0;
}
3 成员函数做友元
在类中加入
friend void GoodGay::visit();
与全局函数做友元的区别是添加作用域
运算符重载
概念:对已有的运算符进行重新定义,赋予其另一种功能,以适应不同的数据类型
1.加号运算符重载
实现两个自定义数据类型相加的运算
(1)成员函数重载+号
成员函数重载本质调用:
Person p3=p1.operator+(p2);
#include<iostream>
using namespace std;
#include<string>
//加号运算符重载
class Person {
public:
//1.成员函数重载+号
Person operator+(Person& p) {
Person temp;
temp.m_A = this->m_A + p.m_A;
temp.m_B = this->m_B + p.m_B;
return temp;
}
int m_A;
int m_B;
};
void test01() {
Person p1;
p1.m_A = 10;
p1.m_B = 10;
Person p2;
p2.m_A = 10;
p2.m_B = 10;
Person p3 = p1 + p2;
cout << "p3.m_A" << p3.m_A << endl;
}
int main() {
test01();
system("pause");
return 0;
}
(2)全局函数重载+号
全局函数重载本质调用:
Person p3=operator+(p1,p2);
#include<iostream>
using namespace std;
#include<string>
//加号运算符重载
class Person {
public:
//1.成员函数重载+号
/*Person operator+(Person& p) {
Person temp;
temp.m_A = this->m_A + p.m_A;
temp.m_B = this->m_B + p.m_B;
return temp;
}*/
int m_A;
int m_B;
};
//2.全局函数重载+号
Person operator+(Person& p1, Person& p2) {
Person temp;
temp.m_A = p1.m_A + p2.m_A;
temp.m_B = p1.m_B + p2.m_B;
return temp;
}
void test01() {
Person p1;
p1.m_A = 10;
p1.m_B = 10;
Person p2;
p2.m_A = 10;
p2.m_B = 10;
Person p3 = p1 + p2;
cout << "p3.m_A" << p3.m_A << endl;
}
int main() {
test01();
system("pause");
return 0;
}
运算符重载也可以发生函数重载
对于内置的数据类型的表达式的运算符是不可更改的
不要滥用运算符重载
2.左移运算符重载
作用:输出自定义数据类型
不会利用成员函数重载<<运算符,因为无法实现在左侧
只能利用全局函数重载<<
ostream & operator<<(ostream &cout,Person p){}
#include<iostream>
using namespace std;
#include<string>
//左移运算符重载
class Person {
public:
int m_A;
int m_B;
};
ostream & operator<<(ostream &cout,Person p) {
//本质 operator<<(cout,p) 简化 cout<<p
cout << "m_A=" << p.m_A << "m_B=" << p.m_B <<endl;
return cout; //为了实现链式编程,cout后追加多个输出
}
void test01(){
Person p;
p.m_A = 10;
p.m_B = 10;
cout << p<<endl;
}
int main() {
test01();
system("pause");
return 0;
}
3.递增运算符重载
作用:实现自己的整型数据
重载前置++运算符
返回引用 是为了一直对一个数据进行操作
重载后置++运算符
传入的int代表占位参数,可以用于区分前置后置递增
此处要返回值,不能返回引用,因为返回的是局部对象
#include<iostream>
using namespace std;
#include<string>
//重载递增运算符
//自定义整型
class MyInt
{
friend ostream& operator<<(ostream& cout, MyInt myint);
public:
MyInt() {
m_num = 0;
}
//重载前置++运算符
//返回引用是为了一直对一个数据进行操作
MyInt& operator++() {
m_num++;
return *this;
}
//重载后置++运算符
//传入的int代表占位参数,可以用于区分前置后置递增
//此处要返回值,不能返回引用,因为返回的是局部对象
MyInt operator++(int) {
//先 记录结果
MyInt temp = *this;
//后 递增
m_num++;
//最后返回记录的结果
return temp;
}
private:
int m_num;
};
//重载左移运算符
ostream& operator<<(ostream& cout, MyInt myint) {
cout << myint.m_num;
return cout;
}
void test01() {
MyInt myint;
cout << ++myint << endl;
}
void test02() {
MyInt myint;
cout << myint++ << endl;
cout << myint << endl;
}
int main() {
//test01();
test02();
system("pause");
return 0;
}
4.赋值运算符重载
c++编译器至少给类添加4个函数
1)默认构造函数(无参,函数体为空)
2)默认析构函数(无参,函数体为空)
3)默认拷贝函数,对属性进行值拷贝
4)赋值运算符operator=对属性进行值拷贝
#include<iostream>
using namespace std;
#include <string>
class Person {
public:
Person(int age) {
m_Age = new int(age);
}
~Person() {
//析构函数,释放空间
if (m_Age != NULL) {
delete m_Age; //释放所指区域
m_Age = NULL; //指针置空
}
}
//运算符重载
Person& operator=(Person &p) {
//返回类型要用&,否则返回的是拷贝构造函数拷贝的值,而不是它本身
//应该先判断是否有属性在堆区,如果有,先进行释放
if (m_Age != NULL) {
delete m_Age;
m_Age = NULL;
}
//进行深拷贝
m_Age = new int(*p.m_Age);
//返回自身
return *this;
}
int* m_Age;
};
void test01() {
Person p1(18);
Person p2(20);
Person p3(30);
//p2=p1; //默认等号是浅拷贝,会出现重复释放空间,所以重载,编程深拷贝
p3=p2 = p1;
cout << "p1年龄" << *p1.m_Age << endl;
cout << "p2年龄" << *p2.m_Age << endl;
cout << "p3年龄" << *p3.m_Age << endl;
}
int main() {
test01();
system("pause");
return 0;
}
5.关系运算符重载
== != > <
返回bool
#include<iostream>
using namespace std;
#include <string>
class Person {
public:
Person(string name,int age) {
m_Name = name;
m_Age = age;
}
//重载==号
bool operator==(Person &p) {
if (this->m_Age == p.m_Age && this->m_Name == p.m_Name)
return true;
else {
return false;
}
}
bool operator!=(Person& p) {
if (this->m_Age != p.m_Age && this->m_Name != p.m_Name)
return false;
else {
return true;
}
}
string m_Name;
int m_Age;
};
void test01() {
Person p1("tom", 18);
Person p2("amy", 18);
if (p1 == p2) {
cout << "p1和p2相等" << endl;
}
else {
cout << "p1和p2不相等" << endl;
}
if (p1 != p2) {
cout << "p1和p2不相等" << endl;
}
else {
cout << "p1和p2相等" << endl;
}
}
int main() {
test01();
system("pause");
return 0;
}
6.函数调用运算符重载
()小括号重载
由于重载后使用的方式非常像函数的调用,因此被称为仿函数
仿函数没有固定的写法,非常灵活
myprint("hello world"); // ()重载实现,使用非常像函数,所以又称仿函数
MyPrint02("hello world!!!"); //函数实现
匿名函数对象 类()
cout << MyAdd()(200, 300) << endl;
#include<iostream>
using namespace std;
#include <string>
class MyPrint {
public:
void operator()(string test) {
cout << test << endl;
}
};
void MyPrint02(string test) {
cout << test << endl;
}
void test01() {
MyPrint myprint;
myprint("hello world"); // ()重载实现,使用非常像函数,所以又称仿函数
MyPrint02("hello world!!!"); //函数实现
}
//仿函数非常灵活,无固定写法,如:
class MyAdd {
public:
int operator()(int a,int b) {
return a + b;
}
};
void test02() {
MyAdd myadd;
int result = myadd(100, 200);
cout << result << endl;
//匿名函数对象 类()
cout << MyAdd()(200, 300) << endl;
}
int main() {
test01();
test02();
system("pause");
return 0;
}