/*头文件String.h如下:*//*头文件String.h如下:*//*头文件String.h如下:*//*头文件String.h如下:*/
#ifndef _STRING_H_
#define _STRING_H_
#include <iostream>
//#include <string>
using namespace std;
/*---------------------------------
创建并实现字符串类的各种功能
18.51.创建String类~18.65.为String类添加字符串加等功能
---------------------------------*/
class String
{
public:
String();
~String(){cout<<"String析构函数执行"<<endl; delete []str;len=0;}
String(const char * const ch);
String(const String &rs);//18.54.用复制构造函数实现字符串的初始化
//String(unsigned short int length);//仅仅提供给重载+调用的构造函数,设置为私有成员
int getlen()const{ return len;}//定义为const修饰的成员函数
//下面最左端的const意指函数返回的指针所指数据是常量,不可修改,只可读
const char* getstr() const{return str;}//靠近花括号的const,其修饰的成员函数体中不能修改任何成员变量(除非该成员变量是mutable修饰的)
//不能调用非const成员函数,因为非const成员函数具备修改成员变量的权限
char& operator[](unsigned short int length);//operator前若有"&",表示按引用返回;无"&",表示按值返回 18.53.限制数组越界
char operator[](unsigned short int length)const;//无"&",表示按值返回 18.54.用复制构造函数实现字符串的初始化1
String& operator=(const String &rs);
String operator+(const String &rs);
void operator+=(const String &rs);
friend ostream& operator<<(ostream &o,const String &str)
{
//o<<"重载<<:"<<str.str;//重载输出
o<<str.str;//重载输出
return o;
}
friend istream& operator>>(istream &o,String &str)
{
cout<<"重载>>:";//重载输入,18.59.用重载输入运算符函数实现字符串的输入
o>>str.str;
//str.len=strlen(str.str);
return o;
}
friend bool operator<(const String &str1,const String &str2)
{
if(strcmp(str1.str,str2.str)<0)
return 1;
return 0;
}
friend bool operator>(const String &str1,const String &str2)
{
if(strcmp(str1.str,str2.str)>0)
return 1;
return 0;
}
friend bool operator==(const String &str1,const String &str2)
{
if(strcmp(str1.str,str2.str)==0)
return 1;
return 0;
}
private:
String(unsigned short int length);//仅仅提供给重载+调用的构造函数,设置为私有成员
int len;
char *str;
};
void String::operator+=(const String &rs)//18.65.为String类添加字符串加等功能
{
cout<<"String类operator+=执行"<<endl;
int total=len+rs.getlen();
String temp(total);
for(int i=0;i<len;i++)
{ temp[i]=str[i];} //temp是String类,故其下标运算符[]将被重载
for(i=0;i<rs.getlen();i++)
{ temp[i+len]=rs[i];}//由于rs是const String类,故其下标运算符[]将被重载
temp[total]='\0';
*this=temp;
}
String String::operator+(const String &rs)//18.61.为String类添加字符串相加功能1
{
cout<<"String类operator+执行"<<endl;
int total=len+rs.getlen();
String temp(total);
for(int i=0;i<len;i++)
{ temp[i]=str[i];} //temp是String类,故其下标运算符[]将被重载
for(i=0;i<rs.getlen();i++)
{ temp[i+len]=rs[i];}//由于rs是const String类,故其下标运算符[]将被重载
temp[total]='\0';
return temp;//按值返回的时候,会自动调用复制构造函数String(const String &rs);
//完毕之后,自动调用析构函数,析构掉对象temp
}
//18.57.用重载赋值运算符函数实现字符串赋值功能
String& String::operator=(const String &rs)
{
cout<<"String类operator=执行"<<endl;
if(this==&rs)
{ return *this;}
delete []str;//this指向的被赋值的字符数组
len=rs.getlen();
str=new char[len+1];
for(int i=0;i<len;i++)
{ str[i]=rs[i];}//由于rs是const String类,故其下标运算符[]将被重载
str[len]='\0';
return *this;
}
char String::operator[](unsigned short int length)const//按值返回
{
cout<<"String类operator[] const执行"<<endl;
if(length>len)
{ return str[len-1];}
else
{ return str[length];}
}
char& String::operator[](unsigned short int length)//重载函数-类外定义书写格式
{
cout<<"String类operator[]执行"<<endl;
if(length>len)
{ return str[len-1];}
else
{ return str[length];}
}
//18.51.创建String类
String::String()
{
cout<<"String执行不带参的构造函数"<<endl;
len=0;
str = new char[1];
str[0]='\0';
}
//18.52.创建可自动调节大小的String类字符串对象
String::String(const char * const ch)//如果const位于*左侧,表示指针所指数据是常量,不能通过解引用修改该数据,指针本身是变量.
{ //如果const位于*右侧,表示指针本身是常量,不能指向其他内存地址,指针所指的数据可以通过解引用修改。
cout<<"String执行带参的构造函数"<<endl;
len=strlen(ch);
str =new char[len+1];
for(int i=0;i<len;i++)
{
str[i]=ch[i];
}
str[len]='\0';
}
String::String(unsigned short int length)//构造一个指定空间大小的空字符串
{
cout<<"String执行带字符串长度参数的构造函数"<<endl;
len=length;
str =new char[len+1];
for(int i=0;i<=len;i++)
{
str[i]='\0';
}
}
//18.54.用复制构造函数实现字符串的初始化
String::String(const String &rs)
{
cout<<"String用复制构造函数实现字符串的初始化"<<endl;
len=rs.getlen();//必须要是const修饰的成员函数
str =new char[len+1];
for(int i=0;i<len;i++)
{
str[i]=rs[i];//由于rs是const String类,故其下标运算符[]将被重载
}
str[len]='\0';
}
#endif
/*程序文件cpp如下:*//*程序文件cpp如下:*//*程序文件cpp如下:*//*程序文件cpp如下:*//*程序文件cpp如下:*/
#include "String.h"
class book
{
public:
book();
~book(){cout<<"book类析构函数执行..."<<endl;}
book(char* Ti,char* Au,char* Nu,float Pr);
book(const book &bk);
const String& gettitle()const{return title;} //按引用方式返回,就不会调用复制构造函数
const String& getauthor()const{return author;}//const成员函数返回const值
String& getauthor(){return author;} //非const成员函数返回非const值
const String& getnumber()const{return number;}
float getprice()const{return price;}
void set_title(const String& ti){title=ti;}
void set_author(const String& au){author=au;}
void set_number(const String& nu){number=nu;}
void set_price(float& pr){price=pr;}
void set_all(const String& ti, const String& au, const String& nu, const float& pr)
{
title=ti;
author=au;
number=nu;
price=pr;
}
private:
String title;
String author;
String number;
float price;
};
book::book():title(""),author(""),number(""),price(0)
{ cout<<"book类不带参数的构造函数执行..."<<endl;}
book::book(char* Ti,char* Au,char* Nu,float Pr):title(Ti),author(Au),number(Nu),price(Pr)
{ cout<<"book类带参数的构造函数执行..."<<endl;}
book::book(const book &bk) //修改编译器默认的复制构造函数
{
cout<<"book类复制构造函数执行..."<<endl;
title =bk.title;
author=bk.author;
number=bk.number;
price =bk.price;
}
void print1(book ab); //按值传递
void print2(const book& ab); //按别名传递
void print3(book* ab); //按地址传递
int main()
{
book a("love","Jack","001",32.1f);
cout<<"a书名:"<<a.gettitle()<<"\t作者:"<<a.getauthor()<<"\t编号:"<<a.getnumber()<<"\t价格:"<<a.getprice()<<endl;
cout<<"调用按值传递print1():"<<endl;
print1(a);
cout<<"a书名:"<<a.gettitle()<<"\t作者:"<<a.getauthor()<<"\t编号:"<<a.getnumber()<<"\t价格:"<<a.getprice()<<endl;
cout<<"调用按别名传递print2():"<<endl;
print2(a);
cout<<"a书名:"<<a.gettitle()<<"\t作者:"<<a.getauthor()<<"\t编号:"<<a.getnumber()<<"\t价格:"<<a.getprice()<<endl;
print3(&a);
cout<<"a书名:"<<a.gettitle()<<"\t作者:"<<a.getauthor()<<"\t编号:"<<a.getnumber()<<"\t价格:"<<a.getprice()<<endl;
return 0;
}
void print1(book ab)
{
cout<<"print1 修改书名前:"<<ab.gettitle()<<"\t作者:"<<ab.getauthor()<<"\t编号:"<<ab.getnumber()<<"\t价格:"<<ab.getprice()<<endl;
ab.set_title("honor");//按值传递的,这里改变的仅仅是临时对象ab的值
cout<<"print1 修改书名后:"<<ab.gettitle()<<"\t作者:"<<ab.getauthor()<<"\t编号:"<<ab.getnumber()<<"\t价格:"<<ab.getprice()<<endl;
}
void print2(const book& ab)
{
cout<<"print2 书名:"<<ab.gettitle()<<"\t作者:"<<ab.getauthor()<<"\t编号:"<<ab.getnumber()<<"\t价格:"<<ab.getprice()<<endl;
// ab.set_title("honor");//const类型的对象ab不可更改,编译报错:
//'set_title' : cannot convert 'this' pointer from 'const class book' to 'class book &'
}
void print3(book* ab)
{
cout<<"print3 修改书名前:"<<ab->gettitle()<<"\t作者:"<<ab->getauthor()<<"\t编号:"<<ab->getnumber()<<"\t价格:"<<ab->getprice()<<endl;
ab->set_title("honor");
cout<<"print3 修改书名后:"<<ab->gettitle()<<"\t作者:"<<ab->getauthor()<<"\t编号:"<<ab->getnumber()<<"\t价格:"<<ab->getprice()<<endl;
}
运行结果:
String执行带参的构造函数
String执行带参的构造函数
String执行带参的构造函数
book类带参数的构造函数执行...
a书名:love 作者:Jack 编号:001 价格:32.1
调用按值传递print1():
String执行不带参的构造函数
String执行不带参的构造函数
String执行不带参的构造函数
book类复制构造函数执行...
String类operator=执行
String类operator[] const执行
String类operator[] const执行
String类operator[] const执行
String类operator[] const执行
String类operator=执行
String类operator[] const执行
String类operator[] const执行
String类operator[] const执行
String类operator[] const执行
String类operator=执行
String类operator[] const执行
String类operator[] const执行
String类operator[] const执行
print1 修改书名前:love 作者:Jack 编号:001 价格:32.1
String执行带参的构造函数
String类operator=执行
String类operator[] const执行
String类operator[] const执行
String类operator[] const执行
String类operator[] const执行
String类operator[] const执行
String析构函数执行
print1 修改书名后:honor 作者:Jack 编号:001 价格:32.1
book类析构函数执行...
String析构函数执行
String析构函数执行
String析构函数执行
a书名:love 作者:Jack 编号:001 价格:32.1
调用按别名传递print2():
print2 书名:love 作者:Jack 编号:001 价格:32.1
a书名:love 作者:Jack 编号:001 价格:32.1
print3 修改书名前:love 作者:Jack 编号:001 价格:32.1
String执行带参的构造函数
String类operator=执行
String类operator[] const执行
String类operator[] const执行
String类operator[] const执行
String类operator[] const执行
String类operator[] const执行
String析构函数执行
print3 修改书名后:honor 作者:Jack 编号:001 价格:32.1
a书名:honor 作者:Jack 编号:001 价格:32.1
book类析构函数执行...
String析构函数执行
String析构函数执行
String析构函数执行
Press any key to continue