嵌入式养成计划-38----C++--匿名对象--友元--常成员函数和常对象--运算符重载

八十七、匿名对象

  • 概念:没有名字对象
  • 格式 :类名();
  • 作用
    1. 用匿名对象给有名对象初始化的
    2. 用匿名对象给对象数组初始化的
    3. 匿名对象作为函数实参使用

示例 :

#include <iostream>
using namespace std;
class Dog
{
private:string name;string color;int *age;
public://无参构造函数Dog(){cout << "Dog::无参构造函数" << endl;}//有参构造函数Dog(string name, string c, int age):name(name),color(c),age(new int(age)){cout << "Dog::有参构造函数" << endl;}//拷贝构造函数Dog(const Dog &other):name(other.name),color(other.color),age(new int(*other.age)){cout << "Dog::拷贝构造函数" << endl;}//拷贝赋值函数Dog &operator=(const Dog &other){if(this != &other)  //避免自己给自己赋值{name = other.name;color = other.color;age = new int(*other.age); //深拷贝赋值函数}cout << "Dog::拷贝赋值函数" << endl;return *this;}//析构函数~Dog(){cout << "Dog::析构函数" << endl;}
};
void fun(Dog g)//Dog g = Dog("大黄","lll",6)
{//函数代码。。。
}
int main()
{Dog d1 = Dog("大黄","lll",6); //匿名对象给有名对象初始化Dog d[3] = {Dog("大","lll",6),Dog("黄","lll",6),Dog("大黄","lll",6)};fun(Dog("大黄","lll",6));  //匿名对象作为函数实参使用return 0;
}

八十八、友元

88.1 作用

  • 可以让其他一些函数或者类访问 另一个类的私有数据成员
  • 友元关键字 : friend

88.2 种类

  1. 全局函数做友元
  2. 类友元
  3. 成员函数做友元

88.3 全局函数做友元

  • 让全局函数访问一个类私有数据成员。

示例 :

#include <iostream>
using namespace std;
class Room {friend void room_friend(Room &r);
private:string keting;
public:string zoulang;Room();
};
Room::Room(){this->keting = "客厅";this->zoulang = "走廊";
}
void room_friend(Room &r){cout << "全局友元函数在访问->" << r.zoulang <<endl;cout << "全局友元函数在访问->" << r.keting <<endl;
}
int main()
{Room r1;room_friend(r1);return 0;
}

88.4 类做友元

  • 一个类去访问另一个类的私有属性。

88.5 成员函数做友元

  • 一个类里的成员函数去访问另一个类的私有属性。

88.6 示例

#include <iostream>
using namespace std;class Room;class Friend_Room{
private:Room *r;
public:Friend_Room();void access_room();
};class Room {
//    friend class Friend_Room;friend void Friend_Room::access_room();
private:string keting;
public:string zoulang;Room();
};
Room::Room(){this->keting = "客厅";this->zoulang = "走廊";
}Friend_Room::Friend_Room(){this->r = new Room;cout << "Friend_Room 的 构造函数" << endl;
}
void Friend_Room::access_room(){cout << "Friend_Room 正在访问 " << this->r->zoulang << endl;cout << "Friend_Room 正在访问 " << this->r->keting << endl;
}int main()
{Friend_Room f_r;f_r.access_room();return 0;
}

88.7 注意

  • 不要过度使用友元,会降低或者破坏封装性
  • 友元不具有交互性,传递性,继承性。

八十九、const修饰的成员函数和对象(常成员函数、常对象)

  • 类中所有的成员函数都可以对类中数据成员进行修改操作,
  • 如果想设计一个成员函数不能对数据成员修改操作,则需要用const修饰的成员函数实现。

89.1 常成员函数

  • 常成员函数 :表示该成员函数不能修改数据成员的值。
  • 格式 :
    返回值类型 函数名(形参列表) const 
    {函数体内容;
    }
    
  • 同名的常成员函数和非常成员函数构成重载关系,
    • 原因:this指针类型不同

89.2 常对象

  • 常对象表示这个对象的数据成员不能被修改。
  • 格式: const 类名 对象名;
  1. 非常对象可以调用常成员函数,也可以调用非常成员函数,优先调用非常成员函数
  2. 常对象只能调用常成员函数,如果没有常成员函数,则报错

示例 :

#include <iostream>
using namespace std;class Stu
{
private:string name;int id;
public:Stu(){}Stu(string  name, int id):name(name),id(id){}//常成员函数void display() const //this指针原型: Stu const * const this;{//this->name = "lisi"; 常成员函数不能对数据成员修改cout << name <<"  "  << id << endl;}//非常成员函数void display() //this指针原型: Stu * const this;{this->name = "lisi";cout << name <<"  "  << id << endl;}
};
int main()
{const Stu s1("zhangsan", 1001);   //常对象s1.display(); //常对象只能调用常成员函数return 0;
}

89.3 mutable关键字

  • mutable修饰成员变量,表示该成员变量可以在常成员函数中被修改 (取消常属性)
    在这里插入图片描述

九十、运算符重载

  • 概念:
    运算符重载就是对运算符重新定义,赋予另一种功能,以适应不同的数据类型。
  • 每种运算符重载都有两种实现方式:
    1. 成员函数实现运算符重载
    2. 全局函数实现运算符重载

90.1 算术运算符重载

种类: +  -   *  /    %
表达式: L   ?   R    (L 左操作数     ?运算符    R右操作数)
左操作数:可以是左值,可以右值,运算过程中不可以被改变
右操作数:可以是左值,可以右值,运算过程中不可以被改变
结果:右值 (不可以被改变)
  • 算术运算符重载实现方式:
    1. 成员函数实现运算符重载

      const 类名 operator#(const 类名 &R) const 
      {具体实现
      }
      

      第一个const 表示结果是右值 不能被改变
      第二个const 表示右操作数运算过程中不能被改变
      第三个const 表示左操作数运算过程中不能被改变

    2. 全局函数实现运算符重载

      const 类名 operator#(const 类名 &L, const 类名 &R)
      {具体实现
      }
      

示例 :

#include <iostream>
using namespace std;class Person
{friend const Person operator+(const Person &L, const Person &R);
private:int a;int b;
public:Person(){}Person(int a, int b):a(a),b(b){}//成员函数实现+号运算符重载
//    const Person operator+(const Person &p) const
//    {
//        Person temp;
//        temp.a = a + p.a;
//        temp.b = b + p.b;
//        return temp;
//    }void show(){cout << " a = " << a << "    b = " << b << endl;}
};//全局函数实现+运算符重载
const Person operator+(const Person &L, const Person &R)
{Person temp;temp.a = L.a + R.a;temp.b = L.b + R.b;return temp;
}
int main()
{Person p1(10,10);Person p2(10,10);//成员函数//简化版本//Person p3 = p1 + p2; //本质上 Person p3 = p1.operator+(p2)Person p3 = p1 + p2; //本质上 Person p3 = operator+(p1, p2)p3.show();return 0;
}

90.2 关系运算符重载

种类: > 、 >= 、 <、 <=、  ==、  !=
表达式: L   ?   R    (L 左操作数     ?运算符    R右操作数)
左操作数:可以是左值,可以右值,运算过程中不可以被改变
右操作数:可以是左值,可以右值,运算过程中不可以被改变
结果: bool类型
  • 关系运算符重载实现方式:
    1. 成员函数实现运算符重载
      bool operator#(const 类名 &R) const
      {具体实现
      }
      
    2. 全局函数实现运算符重载
      bool operator#(const 类名 &L, const 类名 &R)
      {具体实现
      }
      

示例 :

#include <iostream>
using namespace std;
//
class Person
{friend bool operator>(const Person &L, const Person &R);
private:int a;int b;
public:Person(){}Person(int a, int b):a(a),b(b){}//成员函数实现>号运算符重载
//    bool operator>(const Person &R) const
//    {
//        if(a>R.a && b>R.b)
//        {
//            return true;
//        }
//        else
//        {
//            return false;
//        }
//    }void show(){cout << " a = " << a << "    b = " << b << endl;}
};
//全局函数实现>号运算符重
bool operator>(const Person &L, const Person &R)
{if(L.a>R.a && L.b>R.b){return true;}else{return false;}
}
int main()
{Person p1(10,10);Person p2(10,10);if(p3 > p2)  //本质上  p3.operator>(p2)//本质上 operator(p3,p2){cout <<"p3>p2" << endl;}return 0;
}

90.3 赋值运算符重载

种类: = 、+= 、 -= 、*= 、/=  、%=
表达式: L   ?   R    (L 左操作数     ?运算符    R右操作数)
左操作数:是左值,运算过程中要被改变
右操作数:可以是左值,可以右值,运算过程中不可以被改变
结果:自身的引用
  • 赋值运算符重载实现方式:
    1. 成员函数实现运算符重载
      类名 &operator#(const 类名 &R) 
      {具体实现
      }
      
    2. 全局函数实现运算符重载
      类名 &operator#(类名 &L, const 类名 &R) 
      {具体实现
      }
      

示例 :

#include <iostream>
using namespace std;class Person
{friend Person &operator+=(Person &L,const Person &R);
private:int a;int b;
public:Person(){}Person(int a, int b):a(a),b(b){}//成员函数实现+=号运算符重载
//    Person &operator+=(const Person &R)
//    {
//        a += R.a; // a = a + R.a
//        b += R.b;
//        return *this;
//    }void show(){cout << " a = " << a << "    b = " << b << endl;}
};
//全局函数实现+=号运算符重载
Person &operator+=(Person &L,const Person &R)
{L.a += R.a; // a = a + R.aL.b += R.b;return L;
}
int main()
{Person p1(10,10);Person p2(10,10);p3+=p2;  //  p3 = p3 + p2    本质上 p3.operator+=(p2)p3.show();return 0;
}

小作业

  • 整理代码
    • 算术运算符
    • 逻辑运算符
    • 赋值运算符

我写的

#include <iostream>using namespace std;class Stu {//逻辑运算符重载的全局友元函数friend bool operator>(const Stu &l, const Stu &r);friend bool operator>=(const Stu &l, const Stu &r);friend bool operator<(const Stu &l, const Stu &r);friend bool operator<=(const Stu &l, const Stu &r);friend bool operator==(const Stu &l, const Stu &r);friend bool operator!=(const Stu &l, const Stu &r);//赋值运算符重载friend Stu &operator+=(Stu &l, const Stu &r);friend Stu &operator-=(Stu &l, const Stu &r);friend Stu &operator*=(Stu &l, const Stu &r);friend Stu &operator/=(Stu &l, const Stu &r);friend Stu &operator%=(Stu &l, const Stu &r);
private:double high;double weight;
public:Stu(){}Stu(double h, double w):high(h),weight(w){}void show(){cout << "high = " << this->high << endl;cout << "weight = " << this->weight << endl;puts("");}//类内实现运算符重载//算术运算符重载const Stu operator+(const Stu &s)const{Stu t;t.high = this->high + s.high;t.weight = this->weight + s.weight;return t;}const Stu operator-(const Stu &s)const{Stu t;t.high = this->high + s.high;t.weight = this->weight + s.weight;return t;}const Stu operator*(const Stu &s)const{Stu t;t.high = this->high + s.high;t.weight = this->weight + s.weight;return t;}const Stu operator/(const Stu &s)const{Stu t;t.high = this->high + s.high;t.weight = this->weight + s.weight;return t;}const Stu operator%(const Stu &s)const{Stu t;t.high = (int)this->high % (int)s.high;t.weight = (int)this->weight % (int)s.weight;return t;}//重载赋值运算符const Stu &operator=(const Stu &s){this->high = s.high;this->weight = s.weight;return *this;}
};/** 全局函数实现运算符重载* 访问类的私有属性需要添加为类的友元函数
*/
//逻辑运算符重载
bool operator>(const Stu &l, const Stu &r){if(l.high > r.high && l.weight > r.weight)return true;return false;
}
bool operator>=(const Stu &l, const Stu &r){if(l.high >= r.high && l.weight >= r.weight)return true;return false;
}
bool operator<(const Stu &l, const Stu &r){if(l.high < r.high && l.weight < r.weight)return true;return false;
}
bool operator<=(const Stu &l, const Stu &r){if(l.high <= r.high && l.weight <= r.weight)return true;return false;
}
bool operator==(const Stu &l, const Stu &r){if(l.high == r.high && l.weight == r.weight)return true;return false;
}
bool operator!=(const Stu &l, const Stu &r){if(l.high != r.high && l.weight != r.weight)return true;return false;
}//赋值运算符重载
Stu &operator+=(Stu &l, const Stu &r){l.high += r.high;l.weight += r.weight;return l;
}
Stu &operator-=(Stu &l, const Stu &r){l.high -= r.high;l.weight -= r.weight;return l;
}
Stu &operator*=(Stu &l, const Stu &r){l.high *= r.high;l.weight *= r.weight;return l;
}
Stu &operator/=(Stu &l, const Stu &r){l.high /= r.high;l.weight /= r.weight;return l;
}
Stu &operator%=(Stu &l, const Stu &r){l.high  = (int)l.high % (int)r.high;l.weight = (int)l.weight % (int)r.weight;return l;
}int main()
{Stu s1(175, 60);Stu s2(170, 55);Stu s3 = s1 + s2;Stu s4 = s1 - s2;Stu s5 = s1 * s2;Stu s6 = s1 / s2;Stu s7 = s1 % s2;s1.show();s2.show();s3.show();s4.show();s5.show();s6.show();s7.show();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/100073.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在Kubernetes中实现gRPC流量负载均衡

在尝试将gRPC服务部署到Kubernetes集群中时&#xff0c;一些用户&#xff08;包括我&#xff09;面临的挑战之一是实现适当的负载均衡。在深入了解如何平衡gRPC的方式之前&#xff0c;我们首先需要回答一个问题&#xff0c;即为什么需要平衡流量&#xff0c;如果Kubernetes已经…

亘古难题——前端开发or后端开发

一、引言 前端开发 前端开发是创建WEB页面或APP等前端界面呈现给用户的过程&#xff0c;通过HTML&#xff0c;CSS及JavaScript以及衍生出来的各种技术、框架、解决方案&#xff0c;来实现互联网产品的用户界面交互。 前端开发从网页制作演变而来&#xff0c;名称上有很明显的时…

C语言-数组

C 语言支持数组数据结构&#xff0c;数组是一个由若干相同类型变量组成的有序集合。 这里的有序是指数组元素在内存中的存放方式是有序的&#xff0c;即所有的数组都是由连续的内存位置组成。最低的地址对应第一个元素&#xff0c;最高的地址对应最后一个元素。 在 C 语言中&am…

GNU和Linux的关系、 Linux的发行版本、CentOs和RedHat的区别

GNU和Linux的关系 其实&#xff0c;我们通常称之为的"Linux"系统&#xff0c;相对更准确的名称应该称为“GNU/Linux”系统&#xff01; 一个功能完全的操作系统需要许多不同的组成部分&#xff0c;其中就包括内核及其他组件&#xff1b;而在GNU/Linux系统中的内核就…

物联网AI MicroPython传感器学习 之 MQ136硫化氢传感器

学物联网&#xff0c;来万物简单IoT物联网&#xff01;&#xff01; 一、产品简介 MQ136 是一种硫化氢检测传感器&#xff0c;感应范围为 1 - 200ppm。传感元件是 SnO2&#xff0c;它在清洁空气中的电导率较低。当存在 H₂S 气体时&#xff0c;传感器的电导率随着气体浓度的升…

LeetCode 24.两两交换链表中的结点

题目链接 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 题目解析 首先可以特判一下&#xff0c;如果结点数目小于等于1&#xff0c;则直接返回即可&#xff0c;因为数目小于等于1就不需要交换了。 然后我们可以创建一个虚拟的头结点&#xff0c;然…

【力扣2011】执行操作后的变量值

&#x1f451;专栏内容&#xff1a;力扣刷题⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、题目描述二、题目分析 一、题目描述 题目链接&#xff1a;执行操作后的变量值 存在一种仅支持 4 种操作和 1 个变量 …

用IDEA操作数据库--MySQL

IDEA集成了DataGrip的操作数据库的功能 就可以省略我们下载SQLyog/Navicat/DataGrip这些图形化操作工具了 以下是IDEA的使用 输入数据库的用户和密码

陀螺仪传感器解读-Gyro Acce,1

加速度计和陀螺仪的简介 https://www.cnblogs.com/zdxgloomy/articles/4171937.html 加速度计和陀螺仪的使用指南 &#xff0c;代码部分 https://www.amobbs.com/forum.php?modviewthread&tid5510930&_dsign972b156c 模拟加速度计: 1. Accelerometer prinicple. 加…

Java基本数据类型

Java基本数据类型 1 数值型 整型数据类型 数据类型内存空间&#xff08;8位1字节&#xff09;取值范围byte(字节型&#xff09;8位&#xff08;1字节&#xff09;-128~127 &#xff08;2的8次方&#xff09;short(短整型&#xff09;16位&#xff08;2字节&#xff09;-32768~3…

算法练习11——买卖股票的最佳时机 II

122. 买卖股票的最佳时机 II 给你一个整数数组 prices &#xff0c;其中 prices[i] 表示某支股票第 i 天的价格。 在每一天&#xff0c;你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买&#xff0c;然后在 同一天 出售。 返回 你能获得…

运维知识点汇总

一.公共基础 linux常用目录 链接一 链接二 linux系统启动 链接一 链接二 LVM 链接一 磁盘挂载 链接一 文件权限 链接一 二.VLAN详解 链接 三.中间件 单体部署&#xff1a; 优点&#xff1a; &#xff08;1&#xff09;小团队成型即可完成开发-测试-上线&am…

简单实现接口自动化测试(基于python+unittest)

简介 本文通过从Postman获取基本的接口测试Code简单的接口测试入手&#xff0c;一步步调整优化接口调用&#xff0c;以及增加基本的结果判断&#xff0c;讲解Python自带的Unittest框架调用&#xff0c;期望各位可以通过本文对接口自动化测试有一个大致的了解。 引言 为什么要…

软件行业与就业(导师主讲)

在企业软件应用的整体架构体系中&#xff0c;有一部分被称为中间件&#xff0c;那么什么叫中间件&#xff1f; 中间件&#xff08;Middleware&#xff09;是指位于操作系统和应用程序之间的一层软件层&#xff0c;它提供了一组工具和服务&#xff0c;用于简化和增强企业软件应用…

Sentinel入门

文章目录 初始Sentinel雪崩问题服务保护技术对比认识Sentinel微服务整合Sentinel 限流规则快速入门流控模式关联模式链路模式 流控效果warm up排队等待 热点参数限流全局参数限流热点参数限流 隔离和降级FeignClient整合Sentinel线程隔离熔断降级慢调用异常比例、异常数 授权规…

rustlings本地开发环境配置

克隆自己的仓库 首先我们要在github上找到自己仓库并把它克隆到本地 git clone https://github.com/LearningOS/rust-rustlings-2023-autumn-******.git下载插件 rust-analyzer和Git Graph一个可以用来解析rust代码&#xff0c;另一个可以可视化管理git代码库 下载rustling…

HTML5+CSS3+JS小实例:仿优酷视频轮播图

实例:仿优酷视频轮播图 技术栈:HTML+CSS+JS 效果: 源码: 【html】 <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport" content=&quo…

网络安全(骇客)—技术学习

1.网络安全是什么 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 2.网络安全市场 一、是市场需求量高&#xff1b; 二、则是发展相对成熟入…

深入篇【C++】总结<lambda表达式>与<包装器和bind>的使用与意义

深入篇【C】总结&#xff1c;lambda表达式&#xff1e;与&#xff1c;包装器和bind&#xff1e;的使用与意义 一.lambda表达式1.使用语法2.底层本质3.应用意义 二.包装器(适配器)1.使用语法2.解决问题①3.解决问题②4.应用场景:指令操作 三.bind (适配器)1.调整参数位置2.绑定参…

C# Windows 窗体控件中的边距和填充

可以将 Margin 属性、Left、Top、Right、Bottom 的每个方面设置为不同的值&#xff0c;也可以使用 All 属性将它们全部设置为相同的值。 在代码中设置Margin&#xff0c;元素的左边设置为5个单位、上边设置为10个单位、右边设置为15个单位和下边设置为20个单位。 TextBox myT…