1.友元 的三种形式
/*********** 友元 ************
* ①全局函数做友元
* ②类做友元
* ③类成员函数做友元
* **************************/
代码:
#include
#include
using namespace std;
/* ③类函数友元 : 程序规则{ 自上而下,从左往右 }*/
class House; /*提前空声明*/
class Auntie
{
public:
/*** 注意:是类内声明,类外实现(在被友元类后类外实现) ***/
void cleaning(House value); /* 保洁|清洁 函数 ---> 想让该函数做友元*/
void burning(House value); /* 烧房子函数 ---> 不想让该函数做友元*/
};
/*********** 友元 ************
* ①全局函数做友元
* ②类做友元
* ③类成员函数做友元
* **************************/
class House
{
/***** 全局友元函数:友元声明 ******/
friend void detection(House value);
/***** 类:友元声明 *****/
friend class Girls;
/***** 类函数:友元声明 ****/
friend void Auntie::cleaning(House value);
//friend void Auntie::burning(House value); 不想让该函数为友元
public:
int m_corridor = 1; /*走廊*/
protected:
int m_parlor = 2; /*客厅*/
private:
int m_bedroom = 3; /*卧室*/
};
/* ①全局友元函数 */
void detection(House value)
{
cout << "\n————————————————————————————————————————" << endl;
cout << "检测走廊:" << value.m_corridor << endl;
cout << "检测客厅:" << value.m_parlor << endl;
cout << "检测卧室:" << value.m_bedroom << endl;
}
/* ②类友元 */
class Girls /*闺蜜类*/
{
public:
static void visit(House value)
{
cout << "\n————————————————————————————————————————" << endl;
cout << "参观走廊:" << value.m_corridor << endl;
cout << "参观客厅:" << value.m_parlor << endl;
cout << "参观卧室:" << value.m_bedroom << endl;
}
int GetBedroom()const
{
return this->house.m_bedroom; /* 参观卧室 */
}
House house; /* 当成成员 */
};
/* ③类函数友元 : 程序规则{ 自上而下,从左往右 } ,需要在被友元类之后类外实现*/
void Auntie::cleaning(House value) /* 类友元函数 */
{
cout << "\n————————————————————————————————————————" << endl;
cout << "清洁走廊:" << value.m_corridor << endl;
cout << "清洁客厅:" << value.m_parlor << endl;
cout << "清洁卧室:" << value.m_bedroom << endl;
}
void Auntie::burning(House value) /* 非类友元函数 */
{
cout << "\n————————————————————————————————————————" << endl;
// cout << "烧走廊:" << value.m_corridor << endl;
// cout << "烧客厅:" << value.m_parlor << endl;
// cout << "烧卧室:" << value.m_bedroom << endl;
}
int main()
{
/* 1.实例化对象 */
House house;
/* 2.调用友元 */
/* 2.1 调用全局友元函数 */
detection(house);
/* 2.2 调用友元类 */
Girls girls;
girls.visit(house);
cout << "参观卧室:" << girls.GetBedroom() << endl;
/* 2.3 调用类友元函数 */
Auntie auntie;
auntie.cleaning(house); /* 调用类友元函数 : 清洁 */
auntie.burning(house); /* 调用非类友元函数:烧房子*/
return 0;
}
2.运算符号重载 (简单)
/******** 运算符重载 **********************************************
* 支持: 类外 和 类内
* 注意: 调用直接使用运算符时不能同时存在类内和类外定义,只能存其一
* 如果按照本质调用则可以同时存在
*
* —————————————————————— 本质调用
* 类外:实现的时候,必须(满参数),直接调用函数名
* 类内:类内实现,第一个参数不用填,使用this代替,直接调用函数名
* —————————————————————— 套路规则
* 一般情况提供类内运算符重载,且{类内声明,类内实现},不提倡{类内声明类外实现}
代码:
#include
using namespace std;
/******** 运算符重载 **********************************************
* 支持: 类外 和 类内
* 注意: 调用直接使用运算符时不能同时存在类内和类外定义,只能存其一
* 如果按照本质调用则可以同时存在
*
* —————————————————————— 本质调用 ——————————————————————
* 类外:实现的时候,必须(满参数),直接调用函数名
* 类内:类内实现,第一个参数不用填,使用this代替,直接调用函数名
* —————————————————————— 套路规则 ——————————————————————
* 一般情况提供类内运算符重载,且{类内声明,类内实现},不提倡{类内声明类外实现}
* **************************************************************/
class People
{
public:
People(string name = "",int age = 0):m_name(name),m_age(age){} /* 构造函数 */
public:
string m_name; /*姓名*/
int m_age; /*年龄*/
private:
string m_sex; /*性别*/
public:
People operator +(People value2) /*类内声明,类内实现*/
{
People temp;
temp.m_name = this->m_name + value2.m_name;
temp.m_age = this->m_age + value2.m_age;
return temp;
}
};
#if 0/**** 类外运算符重载 *** 假如这里要使用需要在类里面 加友元函数 */
People operator +(People value1,People value2) /*调用类外本质:如果按照本质调用则可以同时存在*/
{
People temp;
temp.m_name = value1.m_name + value2.m_name;
temp.m_age = value1.m_age + value2.m_age;
temp.m_sex = value1.m_sex + value2.m_sex;
return temp;
}
#endif
int main()
{
People people1("张三",18);
People people2("李四",18);
People people3;
/***** 1.直接调用运算符(由C++编译器给你选择) *****/
//people3 = people1 + people2; /* 调用直接使用运算符时不能同时存在类内和类外定义,只能存其一 */
/***** 2.调用类外函数名 *****/
people3 = operator +(people1,people2); /*调用类外本质:如果按照本质调用则可以同时存在*/
/***** 3.调用类内函数名 ******/
//people3 = people1.operator +(people2); /* 张三 + 李四 */
//people3 = people2.operator +(people1); /* 李四 + 张三 */
cout << "姓名:" << people3.m_name << "\t年龄:" << people3.m_age << endl;
return 0;
}
3.运算符重载 (复杂)
重载的函数有 :
/* 四则运算重载 */ (参数的 const 是防止在函数里面改变 数据的值 后面的const 是把函数定义为常量函数,(常量对象只能调用常量函数,别的成员函数都不能调用。 ) ,参数的 & 是一个小的技巧,因为 指针是 4 个字节, 而 类的字节可能 很大!!)
People operator +(const People &value2) const
People operator -(const People &value2) const
People operator *(const People &value2) const
People operator /(const People &value2) const
People operator %(const People &value2) const
/* 四则运算重载,非同类型高阶重载 */ (这里参数不使用指针的原因是 int 类型的字节也是 4个字节)
People operator +(int age) const
People operator +(string name) const
/* 赋值运算符 */
void operator =(const People &value2)
void operator +=(const People &value2)
void operator -=(const People &value2)
void operator /=(const People &value2)
void operator *=(const People &value2)
void operator %=(const People &value2)
/* 赋值运算符,非同类型高阶重载*/
void operator =(string name)
void operator =(int age) //使用 等于符号改变 age 的值
/* 关系运算符 */
bool operator ==(const People &value2)
bool operator !=(const People &value2)
/* 关系运算符,非同类型高阶重载*/
bool operator ==(string name)
/*单目运算符: ++,--(前置和后置的区分,后置需要一个int占位) */
(为什么前置 加了 引用 因为前置需要返回已经改变的 类参数, 后置是返回 没有改变的类参数
i=1;
++i = 2;
i++ =1;
)
People &operator ++() //前置 (前++ )
People &operator --() //前置
const People operator ++(int) //后置
const People operator --(int) //后置
/* 单目运算符: << , >> , & , | ^ */
People operator <<(int num)
People operator >>(int num)
People operator &(int num)
/* 单目运算符 高阶: << , >> , & , | ^ */ (这里有点难 )
/****** 由于遇到了 extern ostream cout 整个程序只有一个流,所以需要权限和引用 */
friend ostream &operator <<(ostream &out,const People &value) (这里的第二个参数可以不要 & , 但是加了 & 可以减少字节的运用!!)
friend istream &operator >>(istream &in,People &value) (这里第二个参数必须使用 & 因为这里是局部变量需要使用引用, 来改变值, 没有引用的话,我们的参数就不会改变 )
/* 其他运算符操作: () 仿函数,通常做算法策略 */
void operator ()(/*参数列表*/)
bool operator ()(int value) /* 一元谓词 */
bool operator ()(int value1,int value2) /* 二元谓词 */
/* 其他运算符操作: [ ] */
int &operator [](int index) //重载中括号
const int operator [](string com) //const 返回的零时变量不可以被改变,就像 ((i++)++)不可以一样。(不能无限套娃!!) 但是 (++(++i))可以无限套娃!!
/* 其他运算符操作 : -> 很明显是指针操作*/ //重载指针
Grade *operator ->()
People.h
#ifndef PEOPLE_H
#define PEOPLE_H
#include
#include
using namespace std;
class People
{
public:
People(string name = "",string sex = "女",int age = 0); /*构造函数*/
public:
string m_name;
string m_sex;
int m_age;
public:
void Print(); /*打印参数信息*/
public: /* 四则运算重载 */
People operator +(const People &value2) const
{
People temp;
temp.m_age = this->m_age + value2.m_age;
temp.m_name = this->m_name + value2.m_name;
temp.m_sex = this->m_sex + value2.m_sex;
return temp;
}
People operator -(const People &value2) const
{
People temp;
temp.m_age = this->m_age - value2.m_age;
temp.m_name = this->m_name + value2.m_name;
temp.m_sex = this->m_sex + value2.m_sex;
return temp;
}
People operator *(const People &value2) const
{
People temp;
temp.m_age = this->m_age * value2.m_age;
temp.m_name = this->m_name + value2.m_name;
temp.m_sex = this->m_sex + value2.m_sex;
return temp;
}
People operator /(const People &value2) const
{
People temp;
temp.m_age = this->m_age / value2.m_age;
temp.m_name = this->m_name + value2.m_name;
temp.m_sex = this->m_sex + value2.m_sex;
return temp;
}
People operator %(const People &value2) const
{
People temp;
temp.m_age = this->m_age % value2.m_age;
temp.m_name = this->m_name + value2.m_name;
temp.m_sex = this->m_sex + value2.m_sex;
return temp;
}
public: /* 四则运算重载,非同类型高阶重载 */
People operator +(int age) const
{
People temp;
temp.m_age = this->m_age + age;
temp.m_name = this->m_name;
temp.m_sex = this->m_sex;
return temp;
}
People operator +(string name) const
{
People temp;
temp.m_age = this->m_age;
temp.m_name = this->m_name + name;
temp.m_sex = this->m_sex;
return temp;
}
public: /* 赋值运算符 */
void operator =(const People &value2)
{
this->m_age = value2.m_age;
this->m_sex = value2.m_sex;
this->m_name = value2.m_name + "牛逼的王";
}
void operator +=(const People &value2)
{
this->m_age += value2.m_age;
this->m_sex += value2.m_sex;
this->m_name += value2.m_name + "牛逼的王";
}
void operator -=(const People &value2)
{
this->m_age -= value2.m_age;
this->m_sex = value2.m_sex;
this->m_name = value2.m_name + "牛逼的王";
}
void operator /=(const People &value2)
{
this->m_age /= value2.m_age;
this->m_sex = value2.m_sex;
this->m_name = value2.m_name + "牛逼的王";
}
void operator *=(const People &value2)
{
this->m_age *= value2.m_age;
this->m_sex = value2.m_sex;
this->m_name = value2.m_name + "牛逼的王";
}
void operator %=(const People &value2)
{
this->m_age %= value2.m_age;
this->m_sex = value2.m_sex;
this->m_name = value2.m_name + "牛逼的王";
}
public: /* 赋值运算符,非同类型高阶重载*/
void operator =(string name)
{
this->m_name = name;
}
void operator =(int age)
{
this->m_age = age;
}
public: /* 关系运算符 */
bool operator ==(const People &value2)
{
if(this->m_name == value2.m_name&&this->m_age == value2.m_age&&this->m_sex == value2.m_sex)
{
return true; /*真*/
}
return false; /*假*/
}
bool operator !=(const People &value2)
{
if(this->m_age != value2.m_age)
{
return true; /*真*/
}
return false; /*假*/
}
public: /* 关系运算符,非同类型高阶重载*/
bool operator ==(string name)
{
if(this->m_name == name)
{
return true; /*真*/
}
return false; /*假*/
}
public: /* 单目运算符: ++,--(前置和后置的区分,后置需要一个int占位) */
People &operator ++()
{
this->m_age += 1;
return *this;
}
People &operator --()
{
this->m_age -= 1;
return *this;
}
const People operator ++(int)
{
/***********People temp(*this) 解释********
*People value1; //变量
*People *ptr = new People;//指针
*People value2(value1); //拷贝构造 - 变量
*People value2(*ptr); //拷贝构造 - 指针
* ________________________________________
*this 是指针 , *指针 === 变量
******************************************/
People temp(*this); /* 拷贝构造 */
this->m_age += 1;
return temp;
}
const People operator --(int)
{
People temp(*this);
this->m_age -= 1;
return temp;
}
public: /* 单目运算符: << , >> , & , | ^ */
People operator <<(int num)
{
People temp(*this);
temp.m_age = temp.m_age << num;
return temp;
}
People operator >>(int num)
{
People temp(*this);
temp.m_age = temp.m_age >> num;
return temp;
}
People operator &(int num)
{
People temp(*this);
temp.m_age = temp.m_age & num;
return temp;
}
public: /* 单目运算符 高阶: << , >> , & , | ^ */
/****** 由于遇到了 extern ostream cout 整个程序只有一个流,所以需要权限和引用 */
friend ostream &operator <<(ostream &out,const People &value)
{
out << value.m_name << "\t"
<< value.m_age << "\t"
<< value.m_sex;
return out;
}
/****** 由于遇到了 extern istream cin 整个程序只有一个流,所以需要权限和引用 */
friend istream &operator >>(istream &in,People &value)
{
cout << "请输入姓名 性别 年龄:";
in >> value.m_name >> value.m_sex >> value.m_age;
return in;
}
public: /* 其他运算符操作: () 仿函数,通常做算法策略 */
void operator ()(/*参数列表*/)
{
cout << "仿函数策略" << endl;
}
bool operator ()(int value) /* 一元谓词 */
{
if(value == 1) return true;
return false;
}
bool operator ()(int value1,int value2) /* 二元谓词 */
{
if(value1 == value2) return true;
return false;
}
public: /* 其他运算符操作: [] */
int addr[10] = {0};
int addr_len = -1; /*当前使用的长度*/
int addr_max = 10; /*最大长度*/
int &operator [](int index)
{
return this->addr[index];
}
const int operator [](string com)
{
if(com == "max") return addr_max;
if(com == "len") return addr_len;
return 0;
}
public: /* 其他运算符操作 : -> 很明显是指针操作*/
/**** 类内部类 ****/
class Grade
{
public:
int language; /*语文成绩*/
int math; /*数学成绩*/
};
/**** 定义变量 ***/
Grade grade = {
.language = 10,
.math = 20
};
/**** 运算符重载 ***/
Grade *operator ->()
{
return &(this->grade);
}
public: /* 不可重载运算符 */
/************************************
*下面是不可重载的运算符列表:
*
* .:成员访问运算符
* .*, ->*:成员指针访问运算符
* :::域运算符
* sizeof:长度运算符
* ?::条件运算符
* #: 预处理符号
**************************************/
};
#endif // PEOPLE_H
People.cpp
#include "people.h"
People::People(string name, string sex, int age)
:m_name(name),m_sex(sex),m_age(age)
{
}
void People::Print() /*打印参数信息*/
{
cout << "\t姓名:" << m_name
<< "\t性别:" << m_sex
<< "\t年龄:" << m_age
<< endl;
}
main.cpp
#include
#include "people.h"
using namespace std;
int main()
{
/*** 双目运算符之四则运算 ***/
People people1("张三","男",18);
People people2("李四","女",19);
/*** 调用四则运算 ***/
People people3;
people3 = people1 + people2;
people3 = people1 - people2;
people3 = people1 * people2;
people3 = people1 / people2;
people3 = people1 % people2;
/*** 调用四则高阶运算 ***/
people3 = people1 + 10;
people3 = people1 + string("老师"); /* 过度 */
/*** 调用赋值运算符 ****/
people3 = people1; /*本质:people3.operator =(people1); */
people3 += people1; /*本质:people3.operator +=(people1);*/
people3 -= people1;
people3 *= people1;
people3 /= people1;
people3 %= people1;
people3 = "王老师";
people3 = 58;
people3.Print();
people1.Print();
/*** 调用逻辑运算符 ****/
cout << "people3和people3是否相等:" << (people3 == people3 ? "==" : "!=") << endl;
cout << "people3和people1是否相等:" << (people3 == people1 ? "==" : "!=") << endl;
cout << "people3和people1是否相等:" << (people3 != people1 ? "!=" : "==") << endl;
/*** 调用高阶逻辑运算符 ****/
cout << "people3和 老师 是否相等:" << (people3 == "王老师" ? "==" : "!=") << endl;
/*** 单目运算符: ++,-- ***/
#if 0
int value = 10;
/**** 前置 ****自己 和 返回值都是 自增1*/
// cout << "++value = " << ++(++value) << endl;
// cout << "value = " << value << endl;
/**** 后置 ****返回当前,自己自增 1*/
cout << "value++ = " << (value++)++ << endl;
cout << "value = " << value << endl;
#else
People people4("张三","男",16);
/**** 前置 ****/
// cout << (--(--(--people4))).m_age << endl;;
// people4.Print();
/**** 后置 ****/
cout << (people4++).m_age << endl;;
cout <<(people4).m_age << endl;;
#endif
/*** 单目运算符: << , >> , & , | ^ ***/
#if 0
int value = 1; /* 0x01 ==== 0000 0011*/
cout << "value << 1 = " << (value << 1) << endl;
cout << "value = " << value << endl;
#else
People people5("张三","男",1); /* 0x01 ==== 0000 0100*/
cout << "(people5 >> 2).m_age = " << (people5 >> 2).m_age << endl;
cout << "people5.m_age = " << people5.m_age << endl;
cout << "(people5 & 0).m_age = " << (people5 & 0).m_age << endl;
cout << "people5.m_age = " << people5.m_age << endl;
/**** 高阶 << 运算符 ****/
//cin >> people5; 输入
cout << people5 << endl;; //输出
#endif
People people;
people(); /* 调用仿函数 */
cout << "是否相等:" << (people(10,20) == true ? "相等" : "不相等") << endl;
people[3] = 5; /* 相当于 people.addr[3] = 5 ,解读当前想要操作的是int addr[3]*/
cout << "people[3] = " << people[3] << endl;
for(int i = 0; i < people["max"];i++)
{
cout << people[i] << ",";
}
cout << endl;
/**** 去操作其他类的直接操作 -> ***/
people->language = 100;
cout << "语文成绩:" << people->language << endl;
return 0;
}
4.继承
People.h
#ifndef PEOPLE_H
#define PEOPLE_H
#include
#include
using namespace std;
/** 封装是隐藏实现 **/
class People
{
public:
People(string name = "",string sex = "女",int age = 0);
public:
string name() const;
void setName(const string &name);
string sex() const;
void setSex(const string &sex);
int age() const;
void setAge(int age);
protected:
string m_name; /*姓名*/
string m_sex; /*性别*/
int m_age; /*年龄*/
};
#endif // PEOPLE_H
People.cpp
#include "people.h"
People::People(string name,string sex,int age)
:m_name(name),m_sex(sex),m_age(age)
{
}
string People::name() const
{
return m_name;
}
void People::setName(const string &name)
{
m_name = name;
}
string People::sex() const
{
return m_sex;
}
void People::setSex(const string &sex)
{
m_sex = sex;
}
int People::age() const
{
return m_age;
}
void People::setAge(int age)
{
m_age = age;
}
Student.h
#ifndef STUDENT_H
#define STUDENT_H
#include "people.h"
class Grade
{
public:
float language; /*语文*/
float math; /*数学*/
float english; /*英语*/
};
class Student : public People
{
public:
Student(string id = "0",string name = "",string sex = "女",int age = 0);
Student(string id ,float language,float math,float english,string name = "",string sex = "女",int age = 0);
Student(string id ,Grade grade = {0,0,0},string name = "",string sex = "女",int age = 0);
/**** 自己实现成员访问运算符 ****/
Grade *operator ->()
{
return &(this->m_grade);
}
string ID() const;
protected:
string m_ID;
Grade m_grade;
};
#endif // STUDENT_H
Student.cpp
#include "student.h"
Student::Student(string id, string name, string sex, int age)
//:m_ID(id),People(name,sex,age),m_grade{0,0,0}
:Student(id,0,0,0,name,sex,age) /*构造函数相互调用*/
{
}
Student::Student(string id, float language, float math, float english, string name, string sex, int age)
:m_ID(id),People(name,sex,age),m_grade{language,math,english}
{
}
Student::Student(string id, Grade grade, string name, string sex, int age)
:Student(id,grade.language,grade.math,grade.english,name,sex,age) /*构造函数相互调用*/
{
}
string Student::ID() const
{
return m_ID;
}
Teacher.h
#ifndef TEACHER_H
#define TEACHER_H
#include "people.h"
class Teacher : public People
{
public:
Teacher(string id = "0",string name = "",string sex = "女",int age = 0);
string ID() const; /*获取工号*/
protected:
string m_ID;/*工号*/
};
#endif // TEACHER_H
Teachar.cpp
#include "teacher.h"
Teacher::Teacher(string id, string name, string sex, int age)
:m_ID(id),People(name,sex,age)
{
}
string Teacher::ID() const
{
return m_ID;
}
main.cpp
#include
#include "student.h"
#include "teacher.h"
using namespace std;
int main()
{
Student stu("10000","王老师","男",18);
Student stu1("10001",10,20,30,"李白","男",650);
Student xxx;
cout << stu1->english << endl;
cout << stu1->language << endl;
cout << stu1->math << endl;
Teacher teacher("10000","李老师","女",16);
cout << teacher.name() << endl;
cout << teacher.ID() << endl;
return 0;
}
/****** 案例 *******
* 人类
* 学生类 和 老师类
* ****************/