版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第十三章类与对象(二)C++程序设计——大模型思维与实践内容导航引言运算符重载静态成员类模板友元应用实例常成员与常对象大模型探究拷贝构造函数类与对象(二)3class
MyString{private:char*Str;//字符串指针int
len;//字符串长度public:void
ShowStr();//显示字符串内容和长度MyString(const
char*
p=NULL);//构造函数MyString(const
MyString&
s);//拷贝构造函数MyString&
operator=(const
MyString&
s);//赋值运算符重载~MyString();//析构函数char&
operator[](int
n);//重载运算符[],处理String对象const
char&
operator[](int
n)const;//重载运算符[],处理constString对象friend
ostream&
operator<<(ostream&
os,const
MyString&
s);friend
istream&
operator>>(istream&
is,MyString&
s);friend
bool
operator==(const
MyString&
s1,const
MyString&
s2);friend
MyString
operator+(const
MyString&
s1,const
MyString&
s2);};例:模仿C++的string类,定义MyString类,以更深入理解string类的实现机制。运算符重载:MyString类
4//显示字符串内容和长度void
MyString::ShowStr(){ cout<<"string:"<<Str<<",length:"<<len<<endl;}运算符重载:MyString类
//构造函数MyString::MyString(const
char*p){if(p){len=strlen(p);//获取字符串长度Str=new
char[len+1];//分配内存strcpy(Str,p);//复制字符串内容}else{len=0;Str=NULL;}}//拷贝构造函数MyString::MyString(constMyString&s){if(s.Str){len=s.len;//复制字符串长度Str=new
char[len+1];//分配内存strcpy(Str,s.Str);//复制字符串内容}else{len=0;Str=NULL;}}5//赋值运算符重载MyString&
MyString::operator=(const
MyString&
s){if(this==&s){ return*this;//处理自赋值}delete[]Str;//释放旧内存if(s.Str){len=s.len;//复制字符串长度Str=new
char[len+1];//分配内存strcpy(Str,s.Str);//复制字符串内容}else{len=0;Str=NULL;}return*this;//返回当前对象的引用}运算符重载:MyString类
//析构函数MyString::~MyString(){
if(Str!=NULL)delete[]Str;//释放内存}//重载运算符[],处理String对象char&
MyString::operator[](int
n){
return
Str[n];}//重载运算符[],处理constString对象const
char&
MyString::operator[](int
n)const{
return
Str[n];}6//重载输出运算符ostream&
operator<<(ostream&
os,const
MyString&
s){os<<s.Str;returnos;}运算符重载:MyString类
//重载输入运算符istream&
operator>>(istream&
is,MyString&
s){char
temp[100];is>>temp;s=MyString(temp);return
is;}//重载相等运算符bool
operator==(const
MyString&
s1,const
MyString&
s2){
return
strcmp(s1.Str,s2.Str)==0;}//重载加法运算符MyString
operator+(const
MyString&
s1,const
MyString&
s2){char*s=new
char[s1.len+s2.len+1];strcpy(s,s1.Str);strcat(s,s2.Str);MyStringresult(s);delete[]
s;//释放临时内存return
result;}7运算符重载:MyString类
int
main(void){MyStringS1("0123456789abcdef");S1.ShowStr();S1[10]='A';cout<<"afterS1[10]=A"<<endl;S1.ShowStr();constMyStringS2(S1);cout<<"S2[3]="<<S2[3]<<endl;cout<<"S1==S2is"<<(S1==S2)<<endl;cout<<"PleaseinputS1:";cin>>S1;MyStringS3;S3=S1+S2;cout<<S3;return
0;}string:0123456789abcdef,length:16afterS1[10]=Astring:0123456789Abcdef,length:16S2[3]=3S1==S2is1PleaseinputS1:abcdabcd0123456789Abcdef
8运算符重载:MyString类
1.内存管理MyString类使用new和delete[]进行动态内存分配和释放。在创建对象时分配内存,销毁对象时释放内存,因此要正确定义构造函数和析构函数。由于该类涉及到了深拷贝,需要定义拷贝构造函数和重载赋值运算符,确保每个对象都有自己独立的内存空间。2.常量成员函数重载的operator[]有两个版本,一个用于非const对象,一个用于const对象。需要理解const成员函数的作用和使用场景。3.友元函数友元函数可以访问类的私有成员,因此重载的运算符都定义为了友元函数。4.输入输出运算符重载重载<<和>>运算符,使得MyString对象可以直接用于标准输入输出流。5.相等运算符重载重载==运算符,使得可以比较两个MyString对象是否相等。6.加法运算符重载重载+运算符,使得可以连接两个MyString对象。
9运算符重载:MyString类
7.赋值运算符重载作用是将一个MyString对象的值赋给另一个MyString对象。函数体的代码解释如下:(1)自赋值检查 if(this==&s){
return*this;//处理自赋值
}(2)释放旧内存:释放当前对象中原有的字符串内存,防止内存泄漏。(3)复制新值:将源对象的字符串内容复制到当前对象中。步骤如下:• 首先检查源对象是否有字符串:如果s.Str不为空,则进行复制。• 获取字符串长度:将源对象的字符串长度赋值给当前对象的len。• 分配内存:为当前对象的字符串分配足够的内存(包括终止符\0)。• 复制字符串内容:使用strcpy函数将源对象的字符串内容复制到当前对象的字符串指针Str。• 处理空字符串:如果源对象的字符串为空,则将当前对象的len设为0,Str设为NULL。(4)返回当前对象的引用,以支持链式赋值。 return*this;//返回当前对象的引用内容导航引言运算符重载静态成员类模板友元应用实例常成员与常对象大模型探究拷贝构造函数类与对象(二)11template<class
T1,class
T2,int
N>class
Student{private:T1
studentID;T2
score[N];public:Student(T1
id):studentID(id){for(int
i=0;i<N;i++)score[i]=0;}void
display(){cout<<"ID:"<<studentID<<endl<<"Score:"<<endl;for(int
i=0;i<N;i++)cout<<score[i]<<"";cout<<endl;}};在类模板中声明非类型参数示例:非类型参数
int
main(){Student<string,int,3>s1("B305");s1.display();Student<int,double,5>s2(1001);s2.display();return
0;}
ID:B305Score:000非类型参数stringstudentID;intscore[3];
intstudentID;doublescore[5];
ID:1001Score:0000012template<class
T1,class
T2=int,int
N=10>class
Student{private:T1
studentID;T2
score[N];public:Student(T1
id):studentID(id){for(int
i=0;i<N;i++)score[i]=0;}void
display();类内声明};C++11及之后的版本允许为非类型参数指定默认值。
非类型参数
int
main(){Student<string>s1("B305");s1.display();Student<int,double>s2(1001);s2.display();Student<int,double,5>s3(1002);s3.display();return
0;}T1=string;T2=intN=10
T1=int;T2=doubleN=10
T1=intT2=doubleN=5//类外实现display()函数template<class
T1,class
T2,int
N>void
Student<T1,T2,N>::display(){cout<<"ID:"<<studentID<<endl<<"Score:"<<endl;for(int
i=0;i<N;i++)cout<<score[i]<<"";cout<<endl;}13非类型参数
int
main(){Student<string>s1("B305");s1.display();Student<int,double>s2(1001);s2.display();Student<int,double,5>s3(1002);s3.display();return
0;}ID:B305Score:0000000000ID:1002Score:00000ID:1001Score:000000000014使用非类型参数的注意事项:(1)非类型参数的类型非类型参数的类型必须是整型、浮点型、枚举型或指针类型等常量表达式。不能是类类型或string、vector等。(2)默认值的类型匹配非类型参数的默认值必须是编译时常量,并且其类型必须与参数声明的类型匹配。如果类型不匹配,编译器将报错。(3)默认参数的连续性如果为类模板的某个参数指定了默认值,那么从这个参数开始,之后的所有参数(如果有的话)都必须指定默认值。然而,这个规则只适用于类型参数和非类型参数的混合情况。对于纯类型参数列表,可以跳过某些参数而只为后面的参数指定默认值,但这在实践中并不常见。非类型参数
public://构造函数MyVector(){size=0;capacity=10;data=new
T[capacity];}~MyVector(){delete[]
data;}
//析构函数bool
isEmpty()const{return
size==0;}//判断是否为空size_t
length()const{return
size;}
//返回长度void
push_back(const
T&
value);
//插入元素void
remove(size_t
index);
//删除元素T&
operator[](size_t
index);
//重载[]下标运算符const
T&
operator[](size_t
index)const;};};15#include
<iostream>#include
<stdexcept>using
namespace
std;template<typename
T>class
MyVector{private:T*data;//动态数组指针size_t
size;//当前元素数量size_t
capacity;//数组容量//扩展容量void
expandCapacity();例:模仿C++的vector类,定义MyVector类,以更深入理解vector类的实现机制。MyVector类
模板类size_t一种无符号整数类型.在32位系统,为32位;在64位系统,为64位//插入元素到末尾template<typename
T>void
MyVector<T>::push_back(const
T&
value){if(size==capacity){//如果数组已满,则扩展容量expandCapacity();}data[size++]=value;}16//扩展容量template<typename
T>void
MyVector<T>::expandCapacity(){capacity=capacity*2;T*newData=new
T[capacity];for(size_ti=0;i<size;++i){ newData[i]=data[i];}delete[]data;data=newData;}MyVector类
数组容量扩展为原来的两倍,并将旧数据复制到新数组中。
expandCapacity方法定义为私有两原因:(1)防止误用:若公有,用户调用不当导致数据不一致(2)自动管理:改方法由类的内部逻辑自动管理,提高代码的健壮性。//重载[]下标运算符template<typename
T>T&
MyVector<T>::operator[](size_t
index){if(index>=size){ throw
out_of_range("Indexoutofrange");}return
data[index];}
template<typename
T>const
T&
MyVector<T>::operator[](size_t
index)const{if(index>=size){ throw
out_of_range("Indexoutofrange");}return
data[index];}17//删除下标index处的元素template<typename
T>void
MyVector<T>::remove(size_t
index){if(index>=size){ throw
out_of_range("Indexoutofrange");}for(size_ti=index;i<size-1;++i){ data[i]=data[i+1];}--size;}MyVector类
18int
main(){MyVector<int>vec;vec.push_back(1);vec.push_back(2);vec.push_back(3);for(size_t
i=0;i<vec.length();++i){ cout<<"元素"
<<i<<":"<<vec[i]<<endl;}vec.remove(1);cout<<"删除元素后:"
<<endl;for(size_t
i=0;i<vec.length();++i){ cout<<"元素"
<<i<<":"<<vec[i]<<endl;}return
0;}MyVector类
元素0:1元素1:2元素2:3删除元素后:元素0:1元素1:3内容导航引言运算符重载静态成员类模板友元应用实例常成员与常对象大模型探究拷贝构造函数类与对象(二)2013.9大模型探究【提问】:学习C++的运算符重载时,教材说:对于形如@obj的一元运算符表达式,如果@被重载,编译器会将其转换为obj.operator@()或operator@(obj)。但是一元运算符++有前置和后置的区分,在重载时怎么区分呢?请举例说明如何重载这两个运算符。探究1【回复】:在C++中,重载一元运算符++时,前置和后置运算符的重载方式有所不同。前置运算符++和后置运算符++的重载需要通过不同的函数签名来区分。前置运算符++的重载函数没有参数,通常返回对自身的引用。后置运算符++的重载函数有一个int类型的参数,这个参数在调用时不使用,但用于区分前置和后置运算符。后置运算符通常返回对象的副本。以下是一个示例,展示如何重载前置和后置运算符++:21#include
<iostream>using
namespace
std;class
Counter{private:int
value;public:Counter():value(0){}//前置++运算符重载Counter&
operator++(){++value;return*this;}//后置++运算符重载Counter
operator++(int){Counter
temp=*this;value++;return
temp;}13.9大模型探究1.前置运算符++重载:
-这个函数没有参数。-它增加对象的value,然后返回对自身的引用。2.后置运算符++重载-这个函数有一个int类型的参数,但在函数体内不使用。-它首先保存对象的当前状态,然后增加value,最后返回保存的副本。
2213.9大模型探究int
getValue()const{ return
value;}};int
main(){Counterc;cout<<"初始值:"
<<c.getValue()<<endl;++c;//调用前置++cout<<"前置++后:"
<<c.getValue()<<endl;c++;//调用后置++cout<<"后置++后:"
<<c.getValue()<<endl;return
0;}3.使用示例-++c调用前置运算符,直接增加value并返回自身。c++调用后置运算符,返回增加前的副本。通过这种方式,可以清晰地区分和重载前置和后置的++运算符。2313.9大模型探究【提问】:能否通过一个实例,演示一下构造函数、拷贝构造函数、析构函数三者的调用时机。探究2【回复】:好的,通过一个对象以值传递的方式传入函数体的实例来演示一下三者的调用时机。24#include
<iostream>using
namespace
std;class
Location{public:Location(int
xx=0,int
yy=0){X=xx;Y=yy;cout
<<
"ConstructorObject.\n";}Location(const
Location
&p)//复制构造函数{X=p.X;Y=p.Y;cout
<<
"Copy_constructorcalled."
<<
endl;}13.9大模型探究构造函数Location(intxx=0,intyy=0):这是
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年中学化学教学调查活动报告
- 2026年幼儿园中秋节活动实施方案设计
- 2026年幼儿园小班迎新活动目标
- 联合国基金月捐协议书
- 供销社国有资产房屋协议书
- (2026版)医院文化建设工作计划范文
- (2026年)作文带着感恩上路
- 股权转让交税协议书范本
- 2026年人教版高二第二学期生物期末学情调研试卷(附答案可下载)
- 竞业协议书经济补偿金不给
- 2025年全国统一高考英语试卷(全国一卷)含答案
- DB62T 3081-2022 绿色建筑工程验收标准
- 学习解读《SLT 631.1水利水电工程单元工程施工质量验收标准 第 1 部分:土石方工程》课件
- 管理学沟通的含义
- 材料物理知到智慧树章节测试课后答案2024年秋南开大学
- 新能源发电技术 课件 第4章 太阳能发电
- 城市合伙人协议 城市合伙人方案(协议)范本
- 《勤奋成就人生》课件
- 2023救灾被服第5部分:毛毯
- LNG仪表调试方案
- GB/T 3871.8-2006农业拖拉机试验规程第8部分:噪声测量
评论
0/150
提交评论