1、友元

为了能访问某个类中的所有成员方法和成员数据

两种方式:

① 友元函数

在类的头文件中增加:friend 函数名(参数);

[例]有一个计算机类,需要对这个计算机的CPU进行升级

头文件:

#pragma once
#include <string>using namespace std;class Computer
{public:Computer();string description();//定义update函数为Computer类的友元函数,可以访问类中的任何数据和方法(在public/private中任意地方都可定义)friend void update(Computer &computer);
private:string cpu;
};

实现:

#include <sstream>
#include "Computer.h"Computer::Computer(){this->cpu = "i7";
}string Computer::description(){stringstream ret;ret << "cpu:" << cpu;return ret.str();
}

实现CPU升级

#include <iostream>
#include "Computer.h"
#include "ComputerService.h"void update(Computer &computer) {computer.cpu = "i9";
}int main() {Computer computer;cout << computer.description() << endl;update(computer);cout << computer.description() << endl;return 0;
}

② 友元类

通过一个类来实现对另一个类的数据成员和成员方法进行访问或修改
[例] 实现一个计算机服务类来实现对计算机的升级,杀毒,空间清理等功能

ComputerService.h

#pragma onceclass Computer;class ComputerService
{public:void update(Computer *computer);void clean(Computer *computer);void kill(Computer *computer);
};

Computer.h

#pragma once
#include <string>
#include "ComputerService.h"using namespace std;class Computer
{public:Computer();string description();
private:string cpu;//可以对另一个类中的指定的成员函数声明为友元
//  friend void ComputerService::update(Computer *computer);friend class ComputerService;   //声明为友元类
};

ComputerService.cpp

#include <iostream>
#include "ComputerService.h"
#include "Computer.h"`void ComputerService::update(Computer *computer)
{computer->cpu = "i9";
}void ComputerService::clean(Computer * computer)
{std::cout << "正在清理电脑[cpu:" << computer->cpu << "]" << endl;
}void ComputerService::kill(Computer * computer)
{std::cout << "正在进行电脑杀毒[cpu:" << computer->cpu << "]" << endl;
}

调用:

#include <iostream>
#include "Computer.h"
#include "ComputerService.h"int main() {Computer computer;cout << computer.description() << endl;ComputerService service;service.update(&computer);service.clean(&computer);service.kill(&computer);cout << computer.description() << endl;return 0;
}

2.运算符重载

- 重载+运算符

方式一:使用成员函数
方式二:使用友元函数

[例] 实现一斤牛肉等于两斤猪肉,一斤羊肉等于三斤猪肉,将牛肉与羊肉相加

猪肉头文件

#pragma once
#include <string>
class Pork
{public:Pork(int weight = 0);std::string description() const;private:int weight;
};

猪肉实现类:

#include <sstream>
#include "Pork.h"Pork::Pork(int weight)
{this->weight = weight;
}std::string Pork::description() const
{std::stringstream ret;ret << "猪肉的重量为:" << weight << "斤";return ret.str();
}

牛肉头文件

#pragma onceclass Pork;
class Mutton;class Beef
{public:Beef(int weight = 0);//方式一: 使用成员函数来进行操作符重载Pork operator+(Mutton mutton);       //当前对象(牛肉)+ 羊肉,返回猪肉Pork operator+(Beef beef);        //当前对象(牛肉)+ 牛肉,返回猪肉//方式二: 使用友元函数来实现操作符重载friend Pork operator+(const Beef &beef, const Mutton &mutton);friend Pork operator+(const Beef &beef1, const Beef &beef2);
private:int weight;
};

牛肉实现类:

#include "Beef.h"
#include "Mutton.h"
#include "Pork.h"Beef::Beef(int weight)
{this->weight = weight;
}Pork Beef::operator+(Mutton mutton)
{int wei = this->weight * 2 + mutton.getWeight() * 3;  //牛肉的价格是猪肉的2倍,羊肉的价格是猪肉的3倍return Pork(wei);   //返回猪肉
}Pork Beef::operator+(Beef beef)
{int wei = (this->weight + beef.weight) * 2;   //牛肉的价格是猪肉的2倍,羊肉的价格是猪肉的3倍return Pork(wei);   //返回猪肉
}

羊肉头文件

#pragma once
class Mutton
{public:Mutton(int weight = 0);int getWeight() const;private:int weight;
};

羊肉类的实现类

#include "Mutton.h"Mutton::Mutton(int weight)
{this->weight = weight;
}int Mutton::getWeight() const
{return this->weight;
}

main函数

#include <iostream>
#include "Beef.h"
#include "Mutton.h"
#include "Pork.h"//友元函数来实现操作符重载
Pork operator+(const Beef &beef,const Mutton &mutton) {int ret = beef.weight * 2 + mutton.getWeight() * 3;return Pork(ret);
}Pork operator+(const Beef &beef1, const Beef &beef2) {int ret = (beef1.weight + beef2.weight) * 2;return Pork(ret);
}int main() {Beef beef(100);Beef beef2(160);Mutton mutton(100);std::cout << (beef + mutton).description() << std::endl;std::cout << beef.operator+(mutton).description() << std::endl;std::cout << (beef + beef).description() << std::endl;Pork p;p = beef + mutton;std::cout << p.description() << std::endl;p = beef + beef2;std::cout << p.description() << std::endl;return 0;
}

- 重载赋值运算符(=)

Boy创建boy1,boy2,boy3,把boy1的内容赋值给boy2,boy3

boy头文件:

#pragma once
#include <string>using namespace std;class Boy
{public:Boy(const char *name = NULL, int age = 0, int salary = 0, int darkHorse = 0);~Boy();string description();/*返回引用类型,便于连续赋值参数使用引用类型, 可以省去一次拷贝参数使用const, 便于保护实参不被破坏*/Boy& operator=(const Boy &boy);private:char *name;int age;int salary;int darkHorse;  //黑马系数int id;static int lastId;
};

boy实现类:

#include <sstream>
#include "Boy.h"int Boy::lastId = 0;Boy::Boy(const char * name, int age, int salary, int darkHorse)
{if (!name) {   //判断name是否为空name = "无名";}this->name = new char[strlen(name)+1]; //申请内存来存储名字strcpy_s(this->name, strlen(name) + 1, name);this->age = age;this->salary = salary;this->darkHorse = darkHorse;id = ++lastId;
}Boy::~Boy()
{delete name;
}string Boy::description()
{stringstream ret;ret << "姓名:" << name << "\t年龄:" << age << "\t薪资:" << salary << "\t黑马系数" << darkHorse << "\tID:" <<id;return ret.str();
}Boy& Boy::operator=(const Boy & boy)
{if (name) {delete name;}name = new char[strlen(boy.name) + 1];strcpy_s(name, strlen(boy.name) + 1, boy.name);this->age = boy.age;this->salary = boy.salary;this->darkHorse = boy.darkHorse;return *this;
}

main函数:

#include <iostream>
#include "Boy.h"int main() {Boy boy1("rock", 30, 20000, 3);Boy boy2, boy3;cout << boy1.description() << endl;cout << boy2.description() << endl;cout << boy3.description() << endl;boy3 = boy2 = boy1;cout << boy1.description() << endl;cout << boy2.description() << endl;cout << boy3.description() << endl;return 0;
}

- 重载关系运算符(> < ==)

直接比较boy(即 boy1>boy2 / boy1<boy2 / boy1==boy2)

boy头文件:

#pragma once
#include <string>using namespace std;class Boy
{public:Boy(const char *name = NULL, int age = 0, int salary = 0, int darkHorse = 0);~Boy();string description();bool operator>(Boy &boy);bool operator<(Boy &boy);bool operator==(Boy &boy);private:char *name;int age;int salary;int darkHorse;    //黑马系数int id;static int lastId;int compareBoys() const;
};

boy实现类

#include <sstream>
#include "Boy.h"int Boy::lastId = 0;Boy::Boy(const char * name, int age, int salary, int darkHorse)
{if (!name) {   //判断name是否为空name = "无名";}this->name = new char[strlen(name)+1]; //申请内存来存储名字strcpy_s(this->name, strlen(name) + 1, name);this->age = age;this->salary = salary;this->darkHorse = darkHorse;id = ++lastId;
}Boy::~Boy()
{delete name;
}string Boy::description()
{stringstream ret;ret << "姓名:" << name << "\t年龄:" << age << "\t薪资:" << salary << "\t黑马系数" << darkHorse << "\tID:" <<id;return ret.str();
}bool Boy::operator>(Boy & boy)
{if (this->compareBoys() > boy.compareBoys()) {return true;}else {return false;}
}bool Boy::operator<(Boy & boy)
{if (this->compareBoys() < boy.compareBoys()) {return true;}else {return false;}
}bool Boy::operator==(Boy & boy)
{if (this->compareBoys() == boy.compareBoys()) {return true;}else {return false;}
}int Boy::compareBoys()const
{int coefficient = salary + (100-age) * 10 + darkHorse * 100;return coefficient;
}

main函数:

#include <iostream>
#include "Boy.h"int main() {Boy boy1("rock", 30, 20000, 3);Boy boy2("martin", 25, 35000, 5);if (boy1 > boy2) {cout << "rock更值得选择" << endl;       }else if(boy1 < boy2){cout << "martin更值得选择" << endl;}else if (boy1 == boy2) {cout << "不分伯仲" << endl;}return 0;
}

- 重载关系运算符[ ]

对象访问使用:对象名[下标],下标使用字符串或数字
[例] 访问boy的age,boy[“age”] 或 boy[0]

boy头文件:

#pragma once
#include <string>#define AGE_KEY          "age"
#define SALARY_KEY      "salary"
#define DARK_HORSE_KEY  "darkHorse"typedef enum
{AGE,SALARY,DARK_HORSE,POWER
} arr;using namespace std;class Boy
{public:Boy(const char *name = NULL, int age = 0, int salary = 0, int darkHorse = 0);~Boy();string description();int operator[](string index);   //下标运算符重载,输入字符串,返回年龄/薪资/黑马系数int operator[](int index);    //下标运算符重载,输入数字,返回年龄/薪资/黑马系数private:char *name;int age;int salary;int darkHorse;   //黑马系数int id;static int lastId;int compareBoys() const;
};

boy类实现:

#include <sstream>
#include "Boy.h"int Boy::lastId = 0;Boy::Boy(const char * name, int age, int salary, int darkHorse)
{if (!name) {   //判断name是否为空name = "无名";}this->name = new char[strlen(name)+1]; //申请内存来存储名字strcpy_s(this->name, strlen(name) + 1, name);this->age = age;this->salary = salary;this->darkHorse = darkHorse;id = ++lastId;
}Boy::~Boy()
{delete name;
}string Boy::description()
{stringstream ret;ret << "姓名:" << name << "\t年龄:" << age << "\t薪资:" << salary << "\t黑马系数" << darkHorse << "\tID:" <<id;return ret.str();
}int Boy::operator[](string index)
{if (index == "age") {return age;}else if (index == "salary") {return salary;}else if (index == "darkHorse") {return darkHorse;}else if (index == "power") {return compareBoys();}else {return -1;}
}int Boy::operator[](int index)
{if (index == 0) {return age;}else if (index == 1) {return salary;}else if (index == 2) {return darkHorse;}else if (index == 3) {return compareBoys();}else {return -1;}
}int Boy::compareBoys()const
{int coefficient = salary + (100-age) * 10 + darkHorse * 100;return coefficient;
}

main函数:

#include <iostream>
#include "Boy.h"int main() {Boy boy1("rock", 30, 20000, 3);Boy boy2("martin", 25, 35000, 5);cout << "年龄:" << boy1[AGE_KEY] << endl;cout << "薪资:" << boy1[SALARY_KEY] << endl;cout << "黑马系数:" << boy1[DARK_HORSE_KEY] << endl;cout << "综合系数:" << boy1["power"] << endl;cout << "-------------------------------" << endl;cout << "年龄:" << boy2[AGE] << endl;cout << "薪资:" << boy2[SALARY] << endl;cout << "黑马系数:" << boy2[DARK_HORSE] << endl;cout << "综合系数:" << boy2[POWER] << endl;return 0;
}

- 重载输入、输出运算符(>> <<)

方式一:使用成员函数(没有实际意义,不建议使用)
方式二:使用友元函数

boy头文件:

#pragma once
#include <string>using namespace std;class Boy
{public:Boy(const char *name = NULL, int age = 0, int salary = 0, int darkHorse = 0);~Boy();string description();//使用友元函数来实现输出输入运算符的重载friend ostream &operator<<(ostream &os, const Boy &boy);friend istream &operator>>(istream &is, Boy &boy);private:char *name;int age;int salary;int darkHorse; //黑马系数int id;static int lastId;int compareBoys() const;
};

boy类实现与前一节相同

main函数:

#include <iostream>
#include "Boy.h"ostream &operator<<(ostream &os, const Boy &boy) {os << "姓名:" << boy.name << "\t年龄:" << boy.age << "\t薪资:" << boy.salary << "\t黑马系数" << boy.darkHorse;return os;}istream &operator>>(istream &is, Boy &boy) {string defName;is >> defName >> boy.age >> boy.salary >> boy.darkHorse;boy.name = new char[defName.length() + 1];                      //申请内存空间strcpy_s(boy.name, defName.length() + 1, defName.c_str());     //拷贝给boy的namereturn is;
}int main() {Boy boy1("rock", 30, 20000, 3);Boy boy2("martin", 25, 35000, 5);cout << boy1 << endl;cout << boy2 << endl;return 0;
}

- 重载输入、输出运算符(>> <<)

① 普通类型转为类类型

[例] 只输入boy的薪资,boy的薪资将会被赋值
方法:创建一个构造函数

boy头文件:

#pragma once
#include <string>using namespace std;class Boy
{public:Boy(const char *name = NULL, int age = 0, int salary = 0, int darkHorse = 0);~Boy();string description();//普通类型转换为类类型Boy(int salary);Boy(char* name);private:char *name;int age;int salary;int darkHorse;    //黑马系数int id;static int lastId;
};

boy类实现:

#include <sstream>
#include "Boy.h"int Boy::lastId = 0;Boy::Boy(const char * name, int age, int salary, int darkHorse)
{if (!name) {   //判断name是否为空name = "无名";}this->name = new char[strlen(name)+1]; //申请内存来存储名字strcpy_s(this->name, strlen(name) + 1, name);this->age = age;this->salary = salary;this->darkHorse = darkHorse;id = ++lastId;
}Boy::~Boy()
{delete name;
}Boy::Boy(int salary)
{const char *name = "无名";this->name = new char[strlen(name) + 1];   //申请内存来存储名字strcpy_s(this->name, strlen(name) + 1, name);this->salary = salary;this->age = 0;this->darkHorse = 0;id = ++lastId;
}Boy::Boy(char * name)
{this->name = new char[strlen(name) + 1];  //申请内存来存储名字strcpy_s(this->name, strlen(name) + 1, name);this->salary = 0;this->age = 0;this->darkHorse = 0;id = ++lastId;
}

main函数:

#include <iostream>
#include "Boy.h"ostream &operator<<(ostream &os, const Boy &boy) {os << "姓名:" << boy.name << "\t年龄:" << boy.age << "\t薪资:" << boy.salary << "\t黑马系数" << boy.darkHorse;return os;}istream &operator>>(istream &is, Boy &boy) {string defName;is >> defName >> boy.age >> boy.salary >> boy.darkHorse;boy.name = new char[defName.length() + 1];                      //申请内存空间strcpy_s(boy.name, defName.length() + 1, defName.c_str());     //拷贝给boy的namereturn is;
}int main() {Boy b1(10000);Boy b2("张分散");cout << boy1.description() << endl;cout << boy2.description() << endl;return 0;
}

② 类类型转为普通类型

[例] 输入男生的所有信息,把这个对象赋值给男生类中的某个数据成员,可以改变数据成员的内容

boy头文件:

#pragma once
#include <string>using namespace std;class Boy
{public:Boy(const char *name = NULL, int age = 0, int salary = 0, int darkHorse = 0);~Boy();string description();//类类型转换为普通类型operator int() const;operator char* () const;private:char *name;int age;int salary;int darkHorse;   //黑马系数int id;static int lastId;
};

boy类实现:

#include <sstream>
#include "Boy.h"int Boy::lastId = 0;Boy::Boy(const char * name, int age, int salary, int darkHorse)
{if (!name) {   //判断name是否为空name = "无名";}this->name = new char[strlen(name)+1]; //申请内存来存储名字strcpy_s(this->name, strlen(name) + 1, name);this->age = age;this->salary = salary;this->darkHorse = darkHorse;id = ++lastId;
}Boy::~Boy()
{delete name;
}Boy::operator int() const
{return compareBoys();
}Boy::operator char*() const
{return name;
}

main函数:

#include <iostream>
#include "Boy.h"ostream &operator<<(ostream &os, const Boy &boy) {os << "姓名:" << boy.name << "\t年龄:" << boy.age << "\t薪资:" << boy.salary << "\t黑马系数" << boy.darkHorse;return os;}istream &operator>>(istream &is, Boy &boy) {string defName;is >> defName >> boy.age >> boy.salary >> boy.darkHorse;boy.name = new char[defName.length() + 1];                      //申请内存空间strcpy_s(boy.name, defName.length() + 1, defName.c_str());     //拷贝给boy的namereturn is;
}int main() {Boy b3("张三",20,30000,4);int power = b3;char *name = b3;cout << power << endl;cout << name << endl;*/return 0;
}

③ 类类型转为类类型

有一个新的类man 可以直接将boy对象赋值给man对象
方法:修改man的构造方法

man头文件:

#pragma once
#include <iostream>using namespace std;class Boy;class Man
{public:Man(Boy &boy);~Man();friend ostream &operator<<(ostream &os, const Man &man);private:char *name;int age;int salary;
};

man实现类:

#include "Man.h"
#include "Boy.h"Man::Man(Boy &boy)
{//  int length = strlen(boy.getName());int length = strlen((char*)boy);name = new char[length+1];strcpy_s(name, length + 1, boy.getName());age = boy[AGE];salary = boy[SALARY];
}Man::~Man()
{delete name;
}ostream &operator<<(ostream &os, const Man &man) {os << "姓名:" << man.name << "\t年龄:" << man.age << "\t薪资:" << man.salary;return os;}

main函数:

#include <iostream>
#include "Boy.h"ostream &operator<<(ostream &os, const Boy &boy) {os << "姓名:" << boy.name << "\t年龄:" << boy.age << "\t薪资:" << boy.salary << "\t黑马系数" << boy.darkHorse;return os;}istream &operator>>(istream &is, Boy &boy) {string defName;is >> defName >> boy.age >> boy.salary >> boy.darkHorse;boy.name = new char[defName.length() + 1];                      //申请内存空间strcpy_s(boy.name, defName.length() + 1, defName.c_str());     //拷贝给boy的namereturn is;
}int main() {Boy boy("张三", 35, 50000, 4);Man man(boy);cout << boy << endl;cout << man << endl;return 0;
}

[注] = () [ ] -> 这四种运算符不能使用友元函数进行重载

不能被重载的运算符:

类别 符号
成员访问 .
域运算 ::
内存长度运算 sizeof
三目运算 ? : :
预处理 #

可以被重载的运算符:

类别 符号
双目运算符 + - * / %
关系运算符 == != < <= > >=
逻辑运算符 与 或 非
单目运算符 +(正号) -(负号) *(指针) &(取地址) ++ –
位运算 &
赋值运算符 = += -= *= /= %= &=
内存分配 new delete new[ ] delete[ ]
其他 ( ) 函数调用 -> 成员访问 [ ] 下标 , 逗号

总结:项目13学的时间太久了,丧失了学习动力,中间有两个星期没能坚持,学习真的是一件孤独且容易放弃的事,后面的学习要继续努力!不因有效果而坚持,应坚持才产生效果,奥利给!!!

C++一周学习总结(2021/05/03)相关推荐

  1. midas MeshFree 2021 R1 Buld 2021.05.03 x64 Multilingual

    为分析者开发的MeshFree软件,能够超越网格划分的局限性.分析者在做分析的时候,网格划分往往是不可避免的工作,网格划分的局限性会直接影响到整个分析.MeshFree软件利用结构化网格,工程师不需要 ...

  2. 周学习进度----03

    周学习进度 --03 周学习进度03 第13周 所花时间: 120min+60min+120min 代码量(行) 300 博客量(篇) 1篇个人博客+2篇团队博客 了解到的知识 团队开发 需求评审的基 ...

  3. 周学习进度---05

    周学习进度 --05 周学习进度05 第15周 所花时间: 120min+60min+120min 代码量(行) 300 博客量(篇) 2篇个人博客+2篇团队博客 了解到的知识 css的相关知识 用户 ...

  4. 2017-2018-1 20155327 《信息安全系统设计基础》第十三周学习总结

    2017-2018-1 20155327 <信息安全系统设计基础>第十三周学习总结 本章要点 程序的机器级表示 计算机执行机器代码,用字节序列编码低级操作,包括处理数据.管理储存器.读写储 ...

  5. 【财经期刊FM-Radio|2021年03月04日】

    title: [财经期刊FM-Radio|2021年03月04日] 微信公众号: 张良信息咨询服务工作室 [今日热点新闻一览↓↓] 科技股拖累纳指跌超2%,ARKK跌入熊市,美债收益率又猛升,美国5年 ...

  6. # 学号 2017-2018-20172309 《程序设计与数据结构》第十一周学习总结

    ---恢复内容开始--- 学号 2017-2018-20172309 <程序设计与数据结构>第十一周学习总结 教材学习内容总结 第23章 初识Android操作系统:一个多用户的Linux ...

  7. 20145240《信息安全系统设计基础》第十二周学习总结

    20145240<信息安全系统设计基础>第十二周学习总结 前三周博客链接 第九周学习总结 第十周学习总结 第十一周学习总结 视频学习内容总结 指针数组与数组指针 数组指针(也称行指针) 定 ...

  8. 分享Silverlight/WPF/Windows Phone一周学习导读(10月30日-11月6日)

    分享Silverlight/WPF/Windows Phone一周学习导读(10月30日-11月6日) 本周Silverlight学习资源更新 Silverlight 定位 niejunhua [学习 ...

  9. Linux第二周学习笔记(11)

    Linux第二周学习笔记(11) 2.17 隐藏权限lsattr_chattr chattr命令:是设置吟唱隐藏权限的命令,更改Linux文件系统上的文件属性. 参数说明: A:表示文件或目录的ati ...

最新文章

  1. 深度揭秘垃圾回收底层,这次让你彻底弄懂她
  2. 怎么设置表格根据窗口自动调整_Word排版技巧之表格美化,你值得拥有!
  3. NewRandomAccessFile failed to Create/Open问题解决
  4. UnicodeDecodeError: 'ascii' codec can't decode byte 0x82 in position 4..... 针对调用文件出现该错误时的解决办法
  5. 推荐一篇讲解各种debug技术的文章,相当不错!
  6. 第四篇:new和delete的基本用法
  7. Java 移位运算符
  8. iOS应用程序审核机制
  9. Oracle Coherence中文教程十二:配置高速缓存
  10. 荣耀智慧屏搭载了鸿蒙os吗,荣耀智慧屏尝鲜鸿蒙OS “一招鲜”能否吃遍天
  11. 武汉大学教务系统爬虫
  12. 最新1000道高频Java面试题,包含25个技术栈等面试攻略(多线程、JVM、高并发、spring、微服务、kafka,redis、分布式)从底层原理到架构
  13. iOS APP转让条件
  14. 互联网的前世今生:Web 1.0、2.0、3.0
  15. 【Spring】1.核心原理解析
  16. 证券基础知识——一手代表多少数量?
  17. 强制卸载软件工具 windows install clear up
  18. 老婆饼就是老婆,会计就是财务
  19. FPGA初学之跑马灯实验
  20. 如何向Maven中央仓库提交自己的Jar包(发布自己的Jar包到中央仓库)

热门文章

  1. OpenSSL生成.key、.crt、.pfx证书(Windows下)
  2. 一篇不错的网文 闻鸡起舞早耕耘,天道酬勤有志人
  3. FA(萤火虫算法)MATLAB源码详细中文注解
  4. ftp文件/文件夹的上传和下载
  5. 信息安全体系建设☞开源入侵检测系统HIDS
  6. “辶”“廴”偏旁的字五笔拆字
  7. amax服务器安装双系统,双系统安装MAX OS X LION的方法
  8. es 集群 number_of_shards、number_of_replicas
  9. 计算机英语专利,计算机专利用英语词汇1500词.pdf
  10. 发明专利名称的撰写原则和技巧总结