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

C++(学习)2024.9.23

目录

运算符重载

1.概念

2.友元函数运算符重载

 3.成员函数运算符重载

4.特殊运算符重载

1.赋值运算符重载

2.类型转换运算符重载

5.注意事项 

std::string字符串类:

模板与容器

模板

1.函数模板

2.类模板

 类内实现

类内声明类外实现


运算符重载

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;
}
http://www.lryc.cn/news/444958.html

相关文章:

  • 大数据处理从零开始————3.Hadoop伪分布式和分布式搭建
  • 跟着问题学12——GRU详解
  • 内核是如何接收网络包的
  • 计算机毕业设计之:基于微信小程序的电费缴费系统(源码+文档+讲解)
  • 【leetcode】环形链表、最长公共前缀
  • C#开发记录如何建立虚拟串口,进行串口通信,以及通信模板
  • 电源设计的艺术:从底层逻辑到工程实践
  • 软媒市场新探索:软文媒体自助发布,开启自助发稿新篇章
  • 【Kubernetes】常见面试题汇总(二十七)
  • 基于单片机巡迹避障智能小车系统
  • Python163邮箱发送:提升发送效率的技巧?
  • springboot中的异步任务
  • Linux学习笔记8 理解Ubuntu网络管理,做自己网络的主人
  • 理解线程的三大特性:原子性、可见性和有序性
  • 英特尔®以太网网络适配器E810-CQDA1 / E810-CQDA2 网卡 规格书 e810 网卡 规格书 Intel100G E810 网卡 白皮书
  • 好用的idea方法分隔符插件
  • 通过 Xshell 无法连接到 Ubuntu
  • Java面试篇基础部分-Synchronized关键字详解
  • 数据结构之线性表——LeetCode:67. 二进制求和,27. 移除元素,26. 删除有序数组中的重复项
  • SQL_HAVING小例子
  • Avalonia第三方UI库Semi.Avalonia用法详解
  • 宠物智能化听诊器的健康管理!
  • MyBatis-Plus 实体类注解
  • 如何写一个自动化Linux脚本去进行等保测试--引言
  • 美团测开OC!
  • HyperWorks的实体几何创建与六面体网格剖分
  • 项目实战:Ingress搭建Nginx+WP论坛+MariaDB
  • UWA支持鸿蒙HarmonyOS NEXT
  • 【齐家网-注册/登录安全分析报告】
  • MyBatis 基本概念