当前位置: 首页 > news >正文

C++(学习)2024.9.23

目录

运算符重载

1.概念

2.友元函数运算符重载

 3.成员函数运算符重载

4.特殊运算符重载

1.赋值运算符重载

2.类型转换运算符重载

5.注意事项 

std::string字符串类:

模板与容器

模板

1.函数模板

2.类模板

 类内实现

类内声明类外实现

容器

1.标准模板库STL

2.概念

3.顺序容器

(1)array数组

运算符重载

1.概念

C++中可以把部分的运算符开做成函数,此时运算符也可以重载。
运算符预定义的操作只能针对基本数据类型。但是对于自定义类型,也需要类似运算操作,此时就可以重新定义这些运算符的功能,使其支持特定类型,完成特定的操作。

可以被重载的运算符:
        算术运算符:+、-、*、/、%、++、--
        位操作运算符:&、|、~、^(位异或)、<<(左移)、>>(右移)
        逻辑运算符:!、&&、||
        比较运算符:<、>、>=、<=、==、!=
        赋值运算符:=、+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>=
        其他运算符:[]、()、->、,、new、delete、new[]、delete[]

不被重载的运算符:
        成员运算符"."、指针运算符"*"、三目运算符" ? : "、sizeof、作用域"::"

运算符重载有两种实现方式:
1.友元函数运算符重载
2.成员函数运算符重载

2.友元函数运算符重载

#include <iostream>
using namespace std;class MyInt
{
private:int a;
public:MyInt(int a){this->a=a;}int get_int(){return a;}friend MyInt operator +(MyInt &i,MyInt &i2);friend MyInt operator ++(MyInt &i);//前置++friend MyInt operator ++(MyInt &i,int);//后置++
};
MyInt operator +(MyInt &i,MyInt &i2)
{return i.a+i2.a;
}
MyInt operator ++(MyInt &i)
{return ++i.a;
}MyInt operator ++(MyInt &i,int)
{return i.a++;
}int main()
{MyInt int1(1);MyInt int2(2);MyInt int3=int1+int2;cout<<"int1: "<<int1.get_int()<<endl;cout<<"int2: "<<int2.get_int()<<endl;cout<<"int3=int1+int2"<<endl;cout<<"++int3: "<<(++int3).get_int()<<endl;cout<<"int3++: "<<(int3++).get_int()<<endl;cout<<"int3: "<<int3.get_int()<<endl;return 0;
}

 3.成员函数运算符重载

        成员函数运算符重载相比于友元函数运算符重载,最主要的区别,在于友元函数的第一个输入参数,在成员函数中使用this指针代替,因此同样的运算符重载,成员函数比友元函数参数少一个。

#include <iostream>
using namespace std;class MyInt
{
private:int a;
public:MyInt(int a){this->a=a;}int get_int(){return a;}MyInt operator +(MyInt &i);MyInt operator ++();//前置++MyInt operator ++(int);//后置++
};
MyInt MyInt::operator +(MyInt &i)
{return this->a+i.a;
}
MyInt MyInt::operator ++()
{return ++this->a;
}MyInt MyInt::operator ++(int)
{return this->a++;
}int main()
{MyInt int1(1);MyInt int2(2);MyInt int3=int1+int2;cout<<"int1: "<<int1.get_int()<<endl;cout<<"int2: "<<int2.get_int()<<endl;cout<<"int3=int1+int2"<<endl;cout<<"++int3: "<<(++int3).get_int()<<endl;cout<<"int3++: "<<(int3++).get_int()<<endl;cout<<"int3: "<<int3.get_int()<<endl;return 0;
}

4.特殊运算符重载

1.赋值运算符重载

        除了之前学习的无参构造函数、拷贝构造函数、析构函数以外,如果程序员不手写,编译器还会添加一个赋值运算符重载函数。

        赋值运算符重载只能使用成员函数运算符实现。

        当类中出现指针类型的成员变量时,默认的赋值运算符重载函数,类似于默认的浅拷贝构造函数,因此需要手动编写解决“浅拷贝”的问题。

#include <iostream>
using namespace std;class MyInt
{int a;
public:MyInt(int a){this->a=a;}int get_int(){return a;}MyInt &operator =(MyInt &i){cout<<"调用赋值运算符重载函数"<<endl;this->a=i.a;return *this;}
};int main()
{MyInt int1(1);MyInt int2(2);cout<<"int1: "<<int1.get_int()<<endl;cout<<"int2: "<<int2.get_int()<<endl;int2=int1;cout<<"int2: "<<int2.get_int()<<endl;return 0;
}

2.类型转换运算符重载

必须使用成员函数运算符重载,且格式比较特殊。

#include <iostream>
using namespace std;class MyInt
{int a;string b="hello";
public:MyInt(int a){this->a=a;}operator int(){return a;}operator string(){return b;}
};int main()
{MyInt int1(1);int a=int1;string b=int1;cout<<"int a = "<<a<<endl;cout<<"string b = "<<b<<endl;return 0;
}

5.注意事项 

1.重载的运算符限制在C++语言中已有的运算符范围,不能创建新的运算符。
2.运算符重载本质上也是函数重载,但是不支持函数默认值设定。
3.重载之后运算符不能改变运算符的优先级和结合性,也不能改变运算符的操作数和语法结构。
4.运算符重载必须基于或包含自定义类型,即不能改变基本数据类的运算规则。
5.重载的功能应该与原有的功能相似,避免没有目的的滥用运算符重载。
6.一般情况下,双目运算符建议使用友元函数运算符重载,单目运算符建议使用成员函数运算符重载。

std::string字符串类:

字符串对象是一种特殊类型的容器,专门设计用于操作字符串。

#include <iostream>
#include <string.h>
using namespace std;int main()
{string s;// 判断是否为空cout<<s.empty()<<endl;  //1string s1="hello";//隐式调用构造函数cout<<s1<<endl; //hellostring s2("world");//显式调用构造函数cout<<s2<<endl; //world//==、!=、> 、< 判断cout<<(s1==s2)<<endl;   //0cout<<(s1!=s2)<<endl;    //1cout<<(s1>s2)<<endl;    //0cout<<(s1<s2)<<endl;    //1string s3(s2);//拷贝构造函数cout<<s3<<endl; //world// 参数1:char * 源字符串// 参数2:保留的字符串数string s4("ABCDE",3);cout<<s4<<endl;     //ABC// 参数1:std::string 源字符串// 参数2:不保留的字符数,从头开始string s5(s2,3);cout<<s5<<endl;     //ld// 参数1:字符数量// 参数2:字符内容 charstring s6(5,'a');cout<<s6<<endl;     //aaaaacout << "原s5 = " << s5 << " " << "原s6 = " << s6 << endl;swap(s5,s6);    // 交换cout << "交换后s5 = " << s5 << " " << "交换后s6 = " << s6 << endl;string s7=s1+s2;//字符串连接cout<<s7<<endl;     //helloworlds7.append("你好世界");// 向后追加字符串cout<<s7<<endl;     //helloworld你好世界s7.push_back('a');// 向后追加单个字符cout<<s7<<endl;     //helloworld你好世界a// 插入// 参数1:插入的位置// 参数2:插入的内容s7.insert(0,"123");cout<<s7<<endl;      //123helloworld你好世界a// 删除字符串// 参数1:起始位置// 参数2:删除的字符数量s7.erase(2,5);cout<<s7<<endl;     //12oworld你好世界a// 替换// 参数1:起始位置// 参数2:被替换的字符数// 参数3:替换的新内容s7.replace(0,3,"++++");cout<<s7<<endl;     //++++world你好世界as7.clear();   // 清空cout<<s7.length()<<endl;     //0string s8="heiheihei";cout<<s8<<endl;     //heiheiheis8="ABCDEFG";    // 重新赋值cout<<s8<<endl;     //ABCDEFG// 参数1:拷贝的目标// 参数2:拷贝的字符数量// 参数3:拷贝的起始位置// C++的string到C语言数组char a[20]={0};s8.copy(a,3,0);cout<<a<<endl;      //ABC// C++ string 到 c string 用到了C语言中的strcpy// c_str C++的字符串转成C语言的字符数组// c_str 返回一个 const char *char b[20]={0};strcpy(b,s8.c_str());cout<<b<<endl;      //ABCDEFGreturn 0;
}

模板与容器

模板

模板可以让类或者函数支持一种通用类型,这种通用类型在实际运行的过程中可以使用任何数据类型,因此可以写一些与类型无关的代码,这种编程方式也被称为“泛型编程”。

通常有两种形式:
1.函数模板
2.类模板

1.函数模板

使一个函数支持模板编程,可以使函数支持通用数据类型。

#include <iostream>
using namespace std;
template<typename T>    // typename也可以是class
T add(T a,T b)
{return a + b;
}int main()
{string str1 = "hello";string str2 = "world";cout << add(str1,str1) << endl;return 0;
}

2.类模板

使一个类支持模板编程,可以使一个类支持通用数据类型。

 类内实现
#include <iostream>
using namespace std;template<class T>
class Test
{
private:T val;
public:Test(T v){val = v;}T get_val()const{return val;}void set_val(const T &val){this->val = val;}
};int main()
{Test<int> t1(20);cout << t1.get_val() << endl;t1.set_val(10);cout << t1.get_val() << endl;t1.set_val(10.32);cout << t1.get_val() << endl;   // 数据窄化10Test<double> t2(2.56);cout << t2.get_val() << endl;t2.set_val(23.12);cout << t2.get_val() << endl;return 0;
}
类内声明类外实现
#include <iostream>
using namespace std;template<class T>
class Test
{
private:T val;
public:Test(T v);T get_val()const;void set_val(const T &val);
};template<class T>
Test<T>::Test(T v)
{val = v;
}template<class T>
T Test<T>::get_val()const
{return val;
}template<class T>
void Test<T>::set_val(const T &val)
{this->val = val;
}int main()
{Test<int> t1(20);cout << t1.get_val() << endl;t1.set_val(10);cout << t1.get_val() << endl;t1.set_val(10.32);cout << t1.get_val() << endl;   // 数据窄化10Test<double> t2(2.56);cout << t2.get_val() << endl;t2.set_val(23.12);cout << t2.get_val() << endl;return 0;
}

容器

1.标准模板库STL

标准模板库(Standard Template Library,STL)是惠普实验室开发的一系列软件的统称。虽说它主要出现到了C++中,但是在被引入C++之前该技术就已经存在了很长时间。
STL的代码从广义上讲分为三类:algorithm(算法)、container(容器)和iterator(迭代器),几乎所有的代码都采用了模板类和模板函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。

2.概念

容器是用来存储数据的集合,数据元素可以是任何类型(因为是使用模板实现)。
容器类的使用,都要引入对应的头文件。

3.顺序容器

顺序容器中每个元素都有固定的位置并呈线性排布,除非使用删除或者插入的操作改变元素的位置。

(1)array数组

array是C++11新增的容器类型,与传统数组相比更加的安全、易于使用。array数组是定长的。没有办法方便的进行伸缩。

#include <iostream>
#include <array>
using namespace std;int main()
{// 创建一个长度为5的int数组array<int,5> arr = {1,2,3}; // 后面两位补零cout << arr[0] << endl; // 1cout << arr[4] << endl; // 0cout << arr.at(2) << endl;  // 3arr[3] = 200;arr[4] = 300;for(int i = 0; i < arr.size(); i++){cout << arr.at(i) << " ";}cout << endl;// for eachfor(int i : arr){cout << i << endl;}return 0;
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • ubuntu如何进行切换内核版本全教程
  • LLM - 理解 多模态大语言模型(MLLM) 的 幻觉(Hallucination) 与相关技术 (七)
  • leetcode91. 解码方法,动态规划
  • 最新Kali Linux超详细安装教程(附镜像包)
  • 『C/C++』整型和字符串相互转换
  • itextsharp报错 PdfReader not opened with owner password
  • 【51实物与仿真】基于51单片机设计的波形/函数发生器(正弦波、锯齿波、三角波、矩形波,设定频率步进值,改变振幅,LCD显示)——文末完整资料链接
  • python中数据处理库,机器学习库以及自动化与爬虫
  • flume系列之:出现数据堆积时临时增大sink端消费能力
  • [spring]应用分层 及 Spring IoCDI
  • Leetcode3289. 数字小镇中的捣蛋鬼
  • Unity 百度AI实现无绿幕拍照抠像功能(详解版)
  • 人工智能之计算机视觉的发展历程与相关技术内容,相应的模型介绍
  • 树上差分+lca 黑暗的锁链
  • 【C#生态园】构建你的C#操作系统:框架选择与实践
  • [rust! #004] [译] Rust 的内置 Traits, 使用场景, 方式, 和原因
  • 【每日笔记】【Go学习笔记】2019-01-10 codis proxy处理流程
  • 【跃迁之路】【477天】刻意练习系列236(2018.05.28)
  • Bootstrap JS插件Alert源码分析
  • HTTP请求重发
  • Webpack4 学习笔记 - 01:webpack的安装和简单配置
  • 包装类对象
  • 如何借助 NoSQL 提高 JPA 应用性能
  • 通过git安装npm私有模块
  • 走向全栈之MongoDB的使用
  • 积累各种好的链接
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • # windows 运行框输入mrt提示错误:Windows 找不到文件‘mrt‘。请确定文件名是否正确后,再试一次
  • #《AI中文版》V3 第 1 章 概述
  • #Spring-boot高级
  • #微信小程序:微信小程序常见的配置传值
  • $(this) 和 this 关键字在 jQuery 中有何不同?
  • (02)Unity使用在线AI大模型(调用Python)
  • (11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】
  • (C++哈希表01)
  • (Repost) Getting Genode with TrustZone on the i.MX
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (翻译)Entity Framework技巧系列之七 - Tip 26 – 28
  • (计算机网络)物理层
  • (算法)N皇后问题
  • (转)Oracle存储过程编写经验和优化措施
  • .axf 转化 .bin文件 的方法
  • .NET Compact Framework 3.5 支持 WCF 的子集
  • .Net Core webapi RestFul 统一接口数据返回格式
  • .net core 使用js,.net core 使用javascript,在.net core项目中怎么使用javascript
  • .NET 应用启用与禁用自动生成绑定重定向 (bindingRedirect),解决不同版本 dll 的依赖问题
  • .NET中的Exception处理(C#)
  • .net专家(高海东的专栏)
  • /etc/fstab 只读无法修改的解决办法
  • ::前边啥也没有
  • @TableId注解详细介绍 mybaits 实体类主键注解
  • [1181]linux两台服务器之间传输文件和文件夹
  • [16/N]论得趣
  • [23] 4K4D: Real-Time 4D View Synthesis at 4K Resolution
  • [AI]文心一言爆火的同时,ChatGPT带来了这么多的开源项目你了解吗