嵌入式学习-C嘎嘎-Day03

news/2024/11/18 6:33:33/

嵌入式学习-C嘎嘎-Day03

1. 友元 friend

1.1 概念

1.2 友元函数

1.3 友元类

1.4 友元成员函数

2. 运算符重载

2.1 概念

2.2 友元函数运算符重载

2.3 成员函数运算符重载

2.4 特殊运算符重载

2.4.1 赋值运算符重载

2.4.2 类型转换运算符重载

2.5 注意事项

3. 字符串类型 string

1. 友元 friend

1.1 概念

定义:

类实现了数据的隐藏与封装,类的成员变量一般定义为私有成员,仅能通过类的成员函数才能读写。如果成员变量定义为公共的,则又破坏了封装性。但是某些情况下,需要频繁读写类的成员变量,特别是在对某些成员函数多次调用时,由于参数传递、类型检查和安全性检查等都需要时间开销,而影响程序的运行效率。

友元是一种定义在类外部的普通函数,但他需要在类体内进行说明,为了和该类的成员函数加以区别,在说明时前面加以关键字friend。友元不是成员函数但是他能够访问类中的私有成员

作用:

在于提高程序的运行效率,但是,他破坏了类的封装性和隐藏性,使得非成员函数能够访问类的私有成员。导致程序维护性变差,因此使用友元要慎用

友元主要的应用场景是运算符重载

用法:

  • 友元函数
  • 友元类
  • 友元成员函数

1.2 友元函数

友元函数是一种在类内说明,但本身属于类外的函数,可以访问类内所有成员。

#include <iostream>using namespace std;class Girl
{
private:
    int age;public:
    Girl(int age):age(age){}    int get_age() const
    {
        return 18;
    }    // 友元关系说明
    friend void get_real_age(Girl& g);
};void get_real_age(Girl& g)
{
    // 获取私有成员的数值并修改
    cout << "真实年龄:" << g.age << endl;
    g.age = 18;
    cout << "修改后的真实年龄:" << g.age << endl;
}int main()
{
    Girl g(40);
    cout << g.get_age() << endl; // 18
    get_real_age(g);
}

需要注意的是:

  • 友元函数没有this指针
  • 友元函数的类内说明可以在任何部分,不受权限的影响
  • 一个函数可以是多个类的友元函数,只需要分别在个各类中说明

1.3 友元类

当一个类B成为了另一个类A的友元类时,类A的所有成员就可以被类B访问了。

#include <iostream>using namespace std;class A
{
private:
    int value  = 1;    // 友元关系说明
    friend class B;
};class B
{
public:
    void access(A& a)
    {
        cout << this << endl;
//        cout << this->value << endl;  错误
        // 读取和修改a的private成员
        cout << a.value++ << endl;
        cout << a.value << endl;
    }
};int main()
{
    A a;
    B b;
    b.access(a);
}

需要注意的是:

  • 友元关系不能被继承
  • 友元关系不具有交换性
  • 友元关系不具有传递性

1.4 友元成员函数

#include <iostream>using namespace std;// 3. 上一步用到了A类,补充A声明
class A;// 2. 上一步中用到了B类,补充B类
class B
{
public:
    void access(A& a);
};class A
{
private:
    int value  = 1;    // 1. 说明友元关系
    friend void B::access(A& a);
};// 4. 补充友元成员函数的内容
void B::access(A &a)
{
    cout << a.value++ << endl;
    cout << a.value << endl;
}int main()
{
    A a;
    B b;
    b.access(a);
}

2. 运算符重载

2.1 概念

函数可以重载,在C++中运算符也可以重载,运算符默认的操作类型只能是基本数据类型,但是对于很多用户自定义类型,也需要类似的运算操作,此时可以重载运算符,赋予这些运算符新的功能,执行对于自定义类型的运算操作。

可以被重载的运算符:

算术运算符:+、-、*、/、%、++、--

位操作运算符:&、|、~、^(位异或)、<<(左移)、>>(右移)

逻辑运算符:!、&&、||

比较运算符:<、>、>=、<=、==、!=

赋值运算符:=、+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>=

其他运算符:[]、()、->、,、new、delete、new[]、delete[]

不被重载的运算符:

成员运算符“.”、指针运算符“*”、三目运算符“? :”、sizeof、作用域“::”

通常有两种运算符重载的方式(部分运算符只支持一种):

  • 友元函数运算符重载
  • 成员函数运算符重载

可以把运算符重载看做是一种特殊的函数重载,运算符是一种特殊的函数。

2.2 友元函数运算符重载

#include <iostream>using namespace std;/**
 * @brief The Integer class 整数类
 */
class Integer
{
private:
    int value;public:
    Integer(int v):value(v){}    int get_value() const
    {
        return value;
    }    friend Integer operator +(const Integer& i1,const Integer& i2);
    friend Integer operator ++(Integer& i); // 前置
    friend Integer operator ++(Integer& i,int); // 后置
};Integer operator +(const Integer& i1,const Integer& i2)
{
    return i1.value + i2.value;
}Integer operator ++(Integer& i)
{
    return ++i.value;
}Integer operator ++(Integer& i,int)
{
    return i.value++;
}int main() {
    Integer i1(1);
    Integer i2(2);
    Integer i3 = i1+i2;
    cout << i3.get_value() << endl; // 3
    cout << (++i3).get_value() << endl; // 4
    cout << (i3++).get_value() << endl; // 4
    cout << i3.get_value() << endl; // 5    return 0;
}

2.3 成员函数运算符重载

成员函数运算符重载与友元函数运算符重载的最大区别是,成员函数运算符重载的输入参数比友元函数运算符重载少一个,因为友元函数的第一个参数在成员函数中使用this指针表示。

#include <iostream>using namespace std;/**
 * @brief The Integer class 整数类
 */
class Integer
{
private:
    int value;public:
    Integer(int v):value(v){}    int get_value() const
    {
        return value;
    }    Integer operator +(const Integer& i);
    Integer operator ++(); // 前置
    Integer operator ++(int); // 后置
};Integer Integer::operator +(const Integer& i)
{
    // this指针可以不写,因为只要不重名编译器自动添加
    return this->value + i.value;
}Integer Integer::operator ++()
{
    return ++this->value;
}Integer Integer::operator ++(int)
{
    return this->value++;
}int main() {
    Integer i1(1);
    Integer i2(2);
    Integer i3 = i1+i2;
    cout << i3.get_value() << endl; // 3
    cout << (++i3).get_value() << endl; // 4
    cout << (i3++).get_value() << endl; // 4
    cout << i3.get_value() << endl; // 5    return 0;
}

2.4 特殊运算符重载

2.4.1 赋值运算符重载

如果程序员不手动在类中编写赋值运算符重载函数,编译器会为这个类自动添加一个默认的赋值运算符重载函数,以便于实现同类型对象的赋值操作。

赋值运算符重载函数只能通过成员函数实现,因为需要this指针。

需要注意的是,如果出现了浅拷贝,也要修改赋值运算符重载函数的逻辑。

#include <iostream>using namespace std;/**
 * @brief The Integer class 整数类
 */
class Integer
{
private:int value;public:Integer(int v):value(v){}int get_value() const{return value;}// 默认的赋值运算符重载函数
    Integer& operator =(const Integer& i){this->value = i.value;return *this;}
};int main() {
    Integer i1(1);
    Integer i2(2);
    i1 = i2; // 赋值运算
    cout << i1.get_value() << endl; // 2return 0;
}

【思考】截止到目前,如果一个成员手写了一个空类,编译器会自动添加哪些内容:

  • 构造函数
  • 析构函数
  • 拷贝构造函数
  • 赋值运算符重载函数

2.4.2 类型转换运算符重载

类型转换运算符重载函数也必须使用成员函数重载,格式比较特殊

#include <iostream>using namespace std;/**
 * @brief The Integer class 整数类
 */
class Integer
{
private:int value;public:Integer(int v):value(v){}int get_value() const{return value;}// 类型转换函数operator int(){return value;}
};int main() {// int → Integer
    Integer i1 = 1; // 编译器自动调用构造函数
    cout << i1.get_value() << endl; // 1// Integer → intint i2 = i1;
    cout << i2 << endl; // 1return 0;
}

2.5 注意事项

  • 运算符重载只能限制在C++已有的范围内,不能创建的新的运算符。
  • 运算符重载不能改变运算符的优先级和结合性。
  • 运算符重载不能改变运算符的操作数和语法结构。
  • 运算符重载的操作数一定包含自定义类型。
  • 运算符重载的功能应该与原有功能相似,避免滥用。
  • 运算符重载不能设置参数默认值。
  • 通常单目运算符优先考虑成员函数,双目运算符优先考虑友元函数。

3. 字符串类型 string

之前对string的学习比较基础,实际上string有诸多字符串处理函数。

#include <iostream>
#include <string.h>using namespace std;int main() {
    string s; // 创建一个空字符串
    cout << s.empty() << endl; // 判断内容是否为空
    // 构造函数,参数const char*
    string s1 = "Thursday";
    string s2("Thursday");
    cout << (s1 == s2) << endl;
    // 拷贝构造函数
    string s3 = s1;
    string s4(s3);
    cout << s3 << " " << s4 << endl;    // 参数1:const char* 原字符串
    // 参数2:保留前几个字符
    string s5("ABCDEFG",2);
    cout << s5 << endl; // AB    s = "ABCDEFG";
    // 参数1:string 原字符串
    // 参数2:不保留前几个字符
    string s6(s,2);
    cout << s6 << endl; // CDEFG    // 参数1:数量
    // 参数2:字符元素
    string s7(5,'A');
    cout << s7 << endl; // AAAAA    swap(s6,s7); // 交换
    cout << s6 << endl;
    cout << s7 << endl;    // 连接
    cout << s6 + s7 << endl;    // 尾插单字符
    s6.push_back('B');
    cout << s6 << endl;    // 尾插string,支持链式调用
    s6.append("CC").append("DDD");
    cout << s6 << endl;    // 在第二个位置插入内容"111"
    s6.insert(1,"111");
    cout << s6 << endl;    // 参数1:替换的起始位置
    // 参数2:替换的字符数
    // 参数3:替换的新内容
    s6.replace(0,3,"*****");
    cout << s6 << endl;    s6.pop_back(); // 删除最后一个字符
    cout << s6 << endl;    s6 = "1234567890";
    // 参数1:删除的起始位置
    // 参数2:删除的字符数
    s6.erase(3,4);
    cout << s6 << endl;    s6.clear(); // 清空
    cout << s6.size() << endl; // 0    s6 = "ABCDEFGHIJK";
    char c[20];
    // 参数1:拷贝的目标
    // 参数2:拷贝的字符数量
    // 参数3:拷贝的起始位置
    s6.copy(c,5,2);
    cout << c << endl;    // C++ string→C string
    strcpy(c,s6.c_str());
    cout << c << endl;    return 0;
}


http://www.ppmy.cn/news/1547924.html

相关文章

比特币前景再度不明,剧烈波动性恐即将回归

比特币市场降温&#xff0c;波动性增加 自特朗普赢得美国总统大选以来&#xff0c;比特币市场的投机狂热有所降温&#xff0c;现货和衍生品市场的活跃度开始减弱。比特币在上周五跌破87000美元&#xff0c;较之前创下的历史高点低了约6500美元。这一变化受到美联储主席鲍威尔讲…

【Mysql 底层原理】MySQL 查询优化器的工作原理:如何生成最优执行计划

&#x1f449;博主介绍&#xff1a; 博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家&#xff0c;WEB架构师&#xff0c;阿里云专家博主&#xff0c;华为云云享专家&#xff0c;51CTO 专家博主 ⛪️ 个人社区&#x…

Elasticsearch面试内容整理-Elasticsearch 基础概念

Elasticsearch 是一个基于 Apache Lucene 的开源分布式搜索和分析引擎,提供强大的全文本搜索、实时数据分析、分布式存储等功能。以下是 Elasticsearch 的一些基础概念: 什么是 Elasticsearch? ● Elasticsearch 是一个用于全文搜索和实时分析的分布式搜索引擎。 ● 开源和可…

el-cascader 使用笔记

1.效果 2.官网 https://element.eleme.cn/#/zh-CN/component/cascader 3.动态加载&#xff08;官网&#xff09; <el-cascader :props"props"></el-cascader><script>let id 0;export default {data() {return {props: {lazy: true,lazyLoad (…

跟李笑来学美式俚语(Most Common American Idioms): Part 10

Most Common American Idioms: Part 10 前言 本文是学习李笑来的Most Common American Idioms这本书的学习笔记&#xff0c;自用。 Github仓库链接&#xff1a;https://github.com/xiaolai/most-common-american-idioms 使用方法: 直接下载下来&#xff08;或者clone到本地…

安全见闻(完整版)

目录 安全见闻1 编程语言和程序 编程语言 函数式编程语言&#xff1a; 数据科学和机器学习领域&#xff1a; Web 全栈开发&#xff1a; 移动开发&#xff1a; 嵌入式系统开发&#xff1a; 其他&#xff1a; 编程语言的方向&#xff1a; 软件程序 操作系统 硬件设备…

【前端知识】Vue组件Vuex详细介绍

vuex组件介绍 概述一、Vuex的核心概念二、Vuex的工作原理三、Vuex的优点四、Vuex的使用场景五、Vuex的使用步骤 如何使用1. 安装 Vuex2. 创建 Store3. 在 Vue 实例中使用 Store4. 在组件中使用 Vuex5. 使用辅助函数简化代码 概述 Vuex是专门为Vue.js应用程序开发设计的状态管理…

YOLOv8改进,YOLOv8通过RFAConv卷积创新空间注意力和标准卷积,包括RFCAConv, RFCBAMConv,二次创新C2f结构,助力涨点

摘要 空间注意力已广泛应用于提升卷积神经网络(CNN)的性能,但它存在一定的局限性。作者提出了一个新的视角,认为空间注意力机制本质上解决了卷积核参数共享的问题。然而,空间注意力生成的注意力图信息对于大尺寸卷积核来说是不足够的。因此,提出了一种新型的注意力机制—…