//
// main.cpp
// _day5
//
// Created by AchesonD16 贪玩巴斯 on 2021/4/22.
//
一、定义数据实体类
/*
//知识点:
//定义你的数据实体类
class MyData()
{
//定义你的类成员
}
//被调函数
void func(MyData *p)
{
//这里写你的处理代码
}
//主函数
void mainfunc()
{
MyData data;//对象创建在栈上,本函数结束后自动退栈,无需处理
MyData *p=new MyData();//对象创建在堆上并直接赋值给指针,本函数结束前需要释放内存
func(&data);//引用实体对象的地址传递
func(p);//直接传递指针p (地址)
if (p)
{
delete p;
p=null;
} // 释放由new创建的对象,释放前做判断,释放后将指针设置null养成好习惯。
}
*/
二、友元
//友元
/*
生活中家里有客厅(Public),有你的卧室(Private)
客厅所有来的客人都允许进去, 但是卧室是私有的,这有你本人能进去
但是,你也可以允许你的好闺蜜好基友进去。
在程序里,有些私有属性 也想让类外特殊的一些函数或者类进行访问,就需要用到友元技术
友元的目的就是让一个 函数 或者 类 访问另一个类中的私有成员
友元的关键字为:
friend
友元的三种实现:
全局函数做友元 friend void goodGay(Building* building1) // friend 后加函数全部声明
类做友元
成员函数做友元
*/
/*
//1、全局函数做友元
#include<iostream>
using namespace std;
class Building
{
//告诉编译器 goodGay全局函数 是Building类的好朋友,可以访问类中的私有内容
friend void goodGay(Building* building1);
public:
Building()
{
this->m_SittingRoom = "客厅";
this->m_BedRoom = "卧室";
}
public:
string m_SittingRoom; //客厅
private:
string m_BedRoom; //卧室
};
void goodGay(Building* building1)
{
cout << "好基友正在访问:" << building1 -> m_SittingRoom << endl;
cout << "好基友正在访问:" << building1 -> m_BedRoom << endl;
}
void test1()
{
Building b;
goodGay(&b);
}
int main()
{
test1();
system("pause");
return 0;
}
结果:
好基友正在访问:客厅
好基友正在访问:卧室
*/
/*
//2、类做友元
#include<iostream>
using namespace std;
class Building; // 先声明类
class goodGay
{
public:
goodGay();
void visit();
private:
Building *building1;
};
class Building
{
//告诉 编译器 goodGay类是Building类的好朋友,可以访问Building类中私有的内容
friend class goodGay;
public:
Building();
public:
string m_SittingRoom; //客厅
private:
string m_BedRoom; //卧室
};
//在类外通过作用域 来调用构造函数赋初值
Building::Building()
{
this->m_SittingRoom = "客厅";
this->m_BedRoom = "卧室";
}
goodGay::goodGay()
{
building1 = new Building;
}
void goodGay::visit()
{
cout << "好基友正在访问:" << building1->m_SittingRoom << endl;
cout << "好基友正在访问:" << building1->m_BedRoom << endl;
}
void test1()
{
goodGay paidaxing;
paidaxing.visit();
}
int main()
{
test1();
system("pause");
return 0;
}
结果:
好基友正在访问:客厅
好基友正在访问:卧室
*/
/*
//3、成员函数做友元
#include<iostream>
using namespace std;
class Building;
class goodGay
{
public:
goodGay();
void visit0(); // 只让visit0函数作为Building的好朋友,可以访问Building中私有内容
void visit1();
private:
Building* building1;
};
class Building
{
//告诉编译器 goodGay类中的visit成员函数 是 Building的好朋友,可访问私有内容
friend void goodGay::visit0();
public:
Building();
public:
string m_SittingRoom; //客厅
private:
string m_BedRoom; //卧室
};
Building::Building()
{
this->m_SittingRoom = "客厅";
this->m_BedRoom = "卧室";
}
goodGay::goodGay()
{
building1 = new Building;
}
void goodGay::visit0()
{
cout << "好基友正在访问:" << building1->m_SittingRoom << endl;
cout << "好基友正在访问:" << building1->m_BedRoom << endl;
}
void goodGay::visit1()
{
cout << "好基友正在访问:" << building1->m_SittingRoom << endl;
// 错误了! 因为m_BedRoom为私有属性 cout << "好基友正在访问:" << building1->m_BedRoom << endl;
}
void test1()
{
goodGay paidaxing;
paidaxing.visit0();
cout << "下面展示不为友元没有权限的访问结果:" << endl;
paidaxing.visit1();
}
int main()
{
test1();
system("pause");
return 0;
}
结果:
好基友正在访问:客厅
好基友正在访问:卧室
下面展示不为友元没有权限的访问结果:
好基友正在访问:客厅
*/
三、运算符重载
//运算符重载
//运算符重载概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型
1、加号运算符重载
/*
//加号运算符重载 格式: Person operator+(const Person& p)
//作用:实现两个自定义数据类型相加的运算
#include<iostream>
using namespace std;
class Person
{
public:
Person()
{};
Person(int a,int b)
{
this->m_A = a;
this->m_B = b;
}
//成员函数实现 + 号运算符重载
Person operator+(const Person& p)
{
Person temp;
temp.m_A = this->m_A + p.m_A;
temp.m_B = this->m_B + p.m_B;
return temp;
}
public:
int m_A;
int m_B;
};
//全局函数实现 + 号运算符重载
//Person operator+ (const Person& p1, const Person& p2)
//{
// Person temp(0, 0);
// temp.m_A = p1.m_A + p2.m_A;
// temp.m_B = p1.m_B + p2.m_B;
// return temp;
//}
//运算符重载 可以发生函数重载
Person operator+ (const Person& p2, int val)
{
Person temp;
temp.m_A = p2.m_A + val;
temp.m_B = p2.m_B + val;
return temp;
}
void test()
{
Person p1(10, 10);
Person p2(20, 15);
//成员函数方式
Person p3 = p2 + p1; //相当于 p2.operator+(p1);
cout << "mA:" << p3.m_A << endl << "mB:" << p3.m_B << endl;
Person p4 = p3 + 10; //相当于 operator+(p3, 10)
cout << "mA:" << p4.m_A << endl << "mB:" << p4.m_B << endl;
}
int main()
{
test();
system("pause");
return 0;
}
结果:
mA:30
mB:25
总结1:对于内置的数据类型的表达式的运算符是不可能改变的
总结2:不要滥用运算符重载
*/
2、左移运算符重载
/*
//左移运算符重载
//作用:可以输出自定义数据类型
#include<iostream>
using namespace std;
class Person
{
friend ostream& operator<< (ostream& out, Person& p); //友元
public:
Person(int a, int b) //有参构造
{
this->m_A = a;
this->m_B = b;
}
//成员函数 实现不了 p << cout 不是我们想要的效果
//void operator << (Person& p)
//{}
private:
int m_A;
int m_B;
};
//全局函数实现左移重载
//osteram对象只能有一个
ostream& operator<< (ostream& out, Person& p)
{
out << "a:" << p.m_A << " b:" << p.m_B;
return out;
}
void test()
{
Person p1(10, 20);
cout << p1 << " hello world" << endl; //链式编程
}
int main()
{
test();
system("pause");
return 0;
}
结果:
a:10 b:20 hello world
总结:重载左移运算符配合友元可以实现输出自定义数据类型
*/
3、递增运算符重载
/*
//递增运算符的重载
//作用: 通过重载递增运算符,实现自己的整型数据
#include<iostream>
using namespace std;
class MyInteger
{
friend ostream& operator << (ostream& out, MyInteger myint);
public:
MyInteger()
{
m_Num = 0;
}
//前置++ 重载递增运算符
MyInteger& operator++()
{
//先++
m_Num++;
//再返回
return *this;
}
//后置++ //后置返回的是
MyInteger operator++(int)
{
//先返回
MyInteger temp = *this; //记录当前本身的值,然后让本身的值加1,
m_Num++; //但是返回的是以前的值,达到先返回后++;
return temp;
}
private:
int m_Num;
};
ostream& operator<<(ostream& out, MyInteger myint)
{
out << myint.m_Num;
return out;
}
//前置++ :先++ 再返回
void test1()
{
MyInteger myInt;
cout << ++myInt << endl;
cout << myInt << endl;
}
//后置++ :先返回值,再++
void test2()
{
MyInteger myInt;
cout << myInt++ << endl;
cout << myInt << endl;
}
int main()
{
test1();
test2();
system("pause");
return 0;
}
结果:
1
1
0
1
//总结:
前置递增返回 引用,后置递增返回 值。
*/
4、赋值运算符重载
/*
//赋值运算符重载
//c++编译器至少给一个类添加4个函数
//1、默认构造函数(无参,函数体为空)
//2、默认析构函数(无参,函数体为空)
//3、默认拷贝构造函数,对属性进行值拷贝
//4、赋值运算符 operator=, 对属性进行值拷贝
//
//如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题
#include<iostream>
using namespace std;
class Person
{
public:
Person(int age) //构造函数
{
//将年龄数据开辟到堆区
m_Age = new int(age);
}
//重载赋值运算符 标准格式
Person& operator=(Person &p)
{
if(m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
//编译器提供的代码是浅拷贝
//m_Age = p.m_Age;
//提供深拷贝 解决浅拷贝的问题
m_Age = new int(*p.m_Age);
//返回自身
return *this;
}
~Person()
{
if(m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
}
//年龄的指针
int *m_Age;
};
void test1()
{
Person p1(18);
Person p2(20);
Person p3(30);
p3 = p2 = p1; //赋值操作
cout << "p1的年龄为:" << *p1.m_Age << endl;
cout << "p2的年龄为:" << *p2.m_Age << endl;
cout << "p3的年龄为:" << *p3.m_Age << endl;
}
int main()
{
//结果1:
test1();
//结果2:
int a = 10;
int b = 20;
int c = 30;
c = b = a;
cout << " a = " << a << endl;
cout << " b = " << b << endl;
cout << " c = " << c << endl;
}
//结果1:
//p1的年龄为:18
//p2的年龄为:18
//p3的年龄为:18
//a = 10
//b = 10
//c = 10
*/
5、关系运算符重载
/*
//关系运算符重载
//作用: 重载关系运算符,可以让两个自定义类型对象进行对比操作
#include<iostream>
using namespace std;
class Person
{
public:
Person(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
}
bool operator==(Person& p)
{
if(this->m_Name == p.m_Name && this->m_Age == p.m_Age)
{
return true;
}
else
{
return false;
}
}
bool operator!=(Person& p)
{
if(this->m_Name == p.m_Name && this->m_Age == p.m_Age)
{
return false;
}
else
{
return true;
}
}
string m_Name;
int m_Age;
};
void test1()
{
//int a = 0;
//int b = 0;
Person a("孙悟空", 18);
Person b("孙悟空", 18);
if(a == b)
{
cout << "a和b相等" << endl;
}
if(a != b)
{
cout << "a和b不相等" << endl;
}
else
{
cout << "a和b相等" << endl;
}
}
int main()
{
test1();
system("pause");
return 0;
}
结果:
a和b相等
a和b相等
*/
6、函数调用运算符重载
/*
//函数调用运算符重载
//函数调用运算符()也可以重载
//由于重载后使用的方法非常像函数的调用,因此称为仿函数
//仿函数没有固定写法,非常灵活
#include<iostream>
using namespace std;
class MyPrint
{
public:
//格式如下!:
void operator()(string text)
{
cout << text << endl;
}
};
void test1()
{
//重载的() 操作符 也称为仿函数
MyPrint myFunc;
myFunc("你好!世界!");
}
class MyAdd
{
public:
int operator()(int v1, int v2)
{
return v1 + v2;
}
};
void test2()
{
MyAdd add;
int ret = add(10, 10);
cout << "ret = " << ret << endl;
//匿名对象调用
cout << "MyAdd()(100, 100) = " << MyAdd()(100, 100) << endl;
}
int main()
{
test1();
test2();
system("pause");
return 0;
}
结果:
你好!世界!
ret = 20
MyAdd()(100, 100) = 200
*/