文章目录
0 运算符重载
对于内置数据类型,编译器了解运算规则;对于自定义数据类型,编译器不了解运算规则。
运算符重载:重新定义已有运算符,赋予其它新功能,以适应不同数据类型。
1 加法运算符重载(+)
作用:实现自定义数据类型的加法运算。
用法:通过实现全局函数(2个参数)
或成员函数(1个参数)
重载加法运算符,即重载编译器的默认函数operateor+
。
注1:在重载加法运算符前,使用自定义数据类型作为加号的操作数时,编译器报错:
没有与这些操作数匹配的“+”运算符
。
注2:运算符重载可发生函数重载,复用函数名。
注3:对于内置数据类型,其表达式的运算符不可改变;不能滥用运算符重载。
示例:全局函数和成员函数实现加法运算符重载
#include <iostream>
using namespace std;
class Object {
public:
int fieldA;
int fieldB;
Object() {}
Object(int a, int b) {
this->fieldA = a;
this->fieldB = b;
}
/* 成员函数实现加法运算符重载 */
//Object operator+(Object &obj) {
// Object temp;
// temp.fieldA = this->fieldA + obj.fieldA;
// temp.fieldB = this->fieldB + obj.fieldB;
//
// return temp;
//}
};
/* 全局函数实现加法运算符重载 */
Object operator+(Object& p, Object& q) {
Object temp;
temp.fieldA = p.fieldA + q.fieldA;
temp.fieldB = p.fieldB + q.fieldB;
return temp;
}
//全局函数的函数重载
Object operator+(Object& p, int num) {
Object temp;
temp.fieldA = p.fieldA + num;
temp.fieldB = p.fieldB + num;
return temp;
}
int main() {
Object m;
m.fieldA = 1;
m.fieldB = 2;
Object n;
n.fieldA = 10;
n.fieldB = 20;
/* 调用成员函数重载加法运算符 */
//Object obj1 = m + n; //等价于m.operator+(n);
//cout << obj1.fieldA << endl; //11
//cout << obj1.fieldB << endl; //22
/* 调用全局函数重载加法运算符 */
Object obj2 = m + n; //等价于operator+(m, n);
cout << obj2.fieldA << endl; //11
cout << obj2.fieldB << endl; //22
//全局函数的函数重载
int num = 100;
Object obj3 = m + num; //等价于operator+(m, 100);
cout << obj3.fieldA << endl; //101
cout << obj3.fieldB << endl; //102
return 0;
}
2 左移运算符重载(<<)
作用:重载左移运算符结合友元,可实现输出自定义数据类型。
用法:通过实现全局函数(cout和对象等2个参数)
重载左移运算符,即重载编译器的默认函数operateor<<
;将全局函数作为友元,实现对类私有成员的访问。
注1:不能通过
成员函数
重载左移运算符,对象调用成员函数时obj.operator<<(cout)
相当于obj << cout
,此时,标准输出流对象cout
在左移运算符<<
的右侧,不满足要求。
注2:标准输出流对象cout
属于ostream类
,需保证全局仅存在唯一的个cout对象,并使用引用的方式接收。
注3:为保证cout << ... << ... << endl;
的链式编程风格,全局函数的返回类型应为ostream类型
。
示例:全局函数和友元实现左移运算符重载
#include <iostream>
using namespace std;
class Object {
/* 全局函数作友元 */
friend ostream& operator<<(ostream &cout, Object &obj);
private:
int fieldA;
int fieldB;
public:
Object() {}
Object(int a, int b) {
this->fieldA = a;
this->fieldB = b;
}
};
/* 全局函数实现左移运算符重载;设置友元访问类的私有成员 */
//cout对象全局唯一,全局函数以引用类型返回
//为实现链式编程,全局函数的返回类型应为ostream类型
ostream& operator<<(ostream &cout, Object &obj) {
cout << "fieldA = " << obj.fieldA << endl;
cout << "fieldB = " << obj.fieldB << endl;
return cout;
}
int main() {
Object o(1, 2);
cout << o << "调用重载的左移运算符" << endl; //链式编程
/*
//输出结果
fieldA = 1
fieldB = 2
调用重载的左移运算符
*/
return 0;
}
3 递增运算符重载(++)
作用:可实现自定义的整型数据。
用法:通过实现成员函数(无参数)
重载递增运算符,即重载编译器的默认函数operateor++
;前置递增的成员函数返回对象的引用类型,后置递增的成员函数返回值(对象的拷贝)。
注1:内置整型变量的递增运算符分为
前置递增
和后置递增
,实现自定义数据类型的递增运算符时,同名成员函数使用占位参数相区分并重载。
注2:
前置递增函数:*this表示当前对象,函数返回类型为引用(别名,即同一个对象,而不是对象的拷贝),否则连续递增时出错。
后置递增函数:*this表示当前对象,函数返回类型为值(对象的拷贝);创建临时对象记录当前对象,先执行递增操作再返回临时对象;临时变量会在函数调用完毕后释放,若函数返回类型为引用(别名,即同一个对象),再次访问时非法(即访问已释放的内存)。
示例:左移运算符重载和成员函数实现递增运算符重载
#include <iostream>
using namespace std;
class MyInteger {
/* 全局函数作友元 */
friend ostream& operator<<(ostream& cout, MyInteger myint);
private:
int num;
public:
//默认无参构造:初始化为0
MyInteger() {
num = 0;
}
//带参构造:初始化为指定值
MyInteger(int number) {
this->num = number;
}
/* 前置递增函数 */
//解引用*this表示当前对象,返回类型为引用(否则连续递增时出错)
MyInteger & operator++() {
this->num++; //等价于 num++;
return *this;
}
/* 后置递增函数 */
//使用int作为占位参数,与前置递增相区分并重载
//解引用*this表示当前对象,返回类型为值(对象)
//创建临时变量并记录当前对象,先递增再返回已记录的临时变量
//临时变量会在函数调用完毕后释放,若函数返回引用(别名,同一个对象),再次访问时非法
MyInteger operator++(int) {
MyInteger cur = *this; //创建临时变量cur,记录当前对象*this
this->num++; //等价于 num++;
return cur; //返回临时变量(临时变量在函数调用完毕后释放)
}
};
/* 全局函数实现左移运算符重载;设置友元访问类的私有成员 */
ostream& operator<<(ostream& cout, MyInteger myint) {
cout << myint.num;
return cout;
}
int main() {
//测试:前置递增++a
MyInteger a(10);
cout << ++a << endl; //11
cout << a << endl; //11
//测试:后置递增b++
MyInteger b(20);
cout << b++ << endl; //20
cout << b << endl; //21
return 0;
}
4 赋值运算符重载(=)
作用:使用深拷贝实现自定义数据类型的赋值及连续赋值操作。
用法:通过实现成员函数(对象等1个参数)
重载赋值运算符,即重载编译器的默认函数operateor=
,使用深拷贝完成自定义数据类型的赋值操作,且函数返回类型为对象的引用类型,支持类似内置数据类型的连续赋值操作,如c = b = a
。
创建一个类时,C++编译器默认会对类添加至少4个函数:
(1)默认构造函数(无参,函数体为空,即空实现)
(2)默认析构函数(无参,函数体为空,即空实现)
(3)默认拷贝构造函数(对属性进行值拷贝)
(4)赋值运算符operator=
函数(对属性进行值拷贝)
注:若类中有属性指向堆区,则赋值操作时存在浅拷贝问题,调用析构函数释放堆区内存时,可能导致同一块内存被重复释放从而程序崩溃,,需使用深拷贝解决。
示例:深拷贝和成员函数实现赋值运算符重载
#include <iostream>
using namespace std;
class Object {
public:
int* pField;
Object() {}
//自定义构造函数:在堆区初始化
Object(int num) {
pField = new int(num); //返回堆区内存地址
}
//自定义析构函数
~Object() {
if (pField != NULL) {
delete pField;
pField = NULL;
}
}
/* 成员函数实现赋值运算符重载 */
//使用深拷贝实现堆区成员赋值
//先判断堆区成员是否为空:非空则释放后再深拷贝
//成员函数返回引用类型,支持连续赋值
Object& operator=(Object &obj) {
//编译器默认的赋值运算符重载是属性浅拷贝(地址值拷贝,指向同一个堆区对象)
//this->pField = obj.pField;
//先判断堆区成员是否为空:非空则释放后再深拷贝
if (pField != NULL) {
delete pField;
pField = NULL;
}
//深拷贝赋值,在堆区新开辟内存
pField = new int(*obj.pField); //通过解引用获取值
//返回当前对象,实现连续赋值
return *this;
}
};
int main() {
Object a(1);
Object b(2);
Object c(3);
cout << "*a.pField =" << *a.pField << endl; //1
cout << "*b.pField =" << *b.pField << endl; //2
cout << "*c.pField =" << *c.pField << endl; //3
//自定义数据类型的连续赋值
c = b = a;
cout << "*a.pField =" << *a.pField << endl; //1
cout << "*b.pField =" << *b.pField << endl; //1
cout << "*c.pField =" << *c.pField << endl; //1
return 0;
}
5 关系运算符重载(==、!=)
作用:比较自定义数据类型的对象。
用法:通过实现成员函数(对象等1个参数)
重载关系运算符,即重载编译器的默认函数operateor==
或operateor!=
。
示例:成员函数实现关系运算符重载
#include <iostream>
using namespace std;
class Object {
public:
int fieldA;
string fieldB;
Object() {}
Object(int num, string str) {
this->fieldA = num;
this->fieldB = str;
}
/* 关系运算符重载 */
bool operator==(Object& obj) {
return (this->fieldA == obj.fieldA) && (this->fieldB == obj.fieldB);
}
bool operator!=(Object& obj) {
return (this->fieldA != obj.fieldA) || (this->fieldB != obj.fieldB);
}
};
int main() {
Object o1(18, "Tom");
Object o2(18, "Jerry");
if (o1 == o2) {
cout << "自定义数据类型相等" << endl;
}
else if(o1 != o2) {
cout << "自定义数据类型不相等" << endl;
}
return 0;
}
6 函数调用运算符重载(())及仿函数
函数调用运算符小括号()
可发生重载,使用方式类似于函数调用,称为仿函数
。
注1:仿函数无固定写法,使用灵活。
注2:可通过匿名对象使用函数调用运算符,如类名()()
,即匿名函数对象
。
用法:通过实现成员函数
重载函数调用运算符,即重载编译器的默认函数operateor()
,并通过创建类的对象进行调用,如对象();
。
示例:成员函数实现函数调用运算符重载
#include <iostream>
using namespace std;
class Sum {
public:
/* 仿函数使用灵活,无固定写法 */
//成员函数1:函数形参只包含1个时,直接打印
void operator()(int num) {
cout << "结果为:" << num << endl;
}
//成员函数2:函数形参包含2个时,求和
int operator()(int num1, int num2) {
return num1 + num2;
}
//成员函数3:函数形参包含3个时,求和
int operator()(int num1, int num2, int num3) {
return num1 + num2 + num3;
}
};
int main() {
/* 1.通过对象调用 */
Sum sum;
sum(1); //1 //调用成员函数1
int res1 = sum(1, 2); //调用成员函数2
sum(res1); //3 //调用成员函数1
int res2 = sum(1, 2, 3); //调用成员函数2
sum(res2); //6 //调用成员函数1
/* 2.通过匿名对象调用-匿名函数对象 */
//类名()为匿名对象,第二个小括号为函数调用运算符重载
Sum()(1); //1 //调用成员函数1
return 0;
}
7 指针运算符重载(指针指向->、解引用*)
背景:在堆区创建对象并使用完毕后,需显式使用delete操作符
调用析构函数从而释放对象,否则会导致内存泄露。
注:对象指针调用成员函数
p->func()
等价于对象调用成员函数(*p).func()
。
作用:利用智能指针托管new操作符
创建的堆区对象,无需手动使用delete操作符
释放堆区内存。
用法:
(1)模拟智能指针类
,使用装饰者模式包装目标类,通过在栈区创建与释放智能指针类对象,实现堆区目标类对象的自动释放。即栈区智能指针类对象释放并调用析构函数时,会内在地调用堆区目标类对象的析构函数。
(2)通过实现成员函数
重载指针相关的运算符,如指针指向运算符 ->
和解引用运算符 *
,即重载编译器的默认函数operateor->
和operateor*
。
注:重载
指针指向运算符 ->
时,通过智能指针类对象返回指向目标类对象的指针,即smartPointer->
返回pObj
,则对象指针调用成员函数pObj->func()
等价于smartPointer->->func()
,编译器内部会将2个指针指向运算符->->
简化为1个->
。
注:智能指针:使用
类模板
,托管new操作符创建的堆区对象,避免堆区内存泄露。
C++98:auto_ptr<Object> 指针变量名(new Object);
。
C++11:unique_ptr<Object> 指针变量名(new Object);
,需包含头文件#include <memory>
示例:模拟智能指针类重载指针运算符,托管堆区对象
#include <iostream>
using namespace std;
/* 目标类 */
class Object {
private:
int field;
public:
//构造函数
Object() {
cout << "Object目标类的默认无参构造函数被调用" << endl;
}
Object(int num) {
this->field = num;
cout << "Object目标类的有参构造函数被调用" << endl;
}
//析构函数
~Object() {
cout << "Object目标类的析构函数被调用" << endl;
}
//成员函数:显示私有成员属性
void func() {
cout << "私有成员field = " << this->field << endl;
}
};
/* 智能指针类:包装并托管目标类的堆区对象 */
class SmartPointer {
private:
Object* pObj;
public:
//构造函数
SmartPointer(Object *p) {
this->pObj = p;
cout << "SmartPointer智能指针类的有参构造函数被调用" << endl;
}
//析构函数:自动调用目标类Object的析构函数
~SmartPointer() {
cout << "SmartPointer智能指针类的析构函数被调用" << endl;
//调用目标类Object的析构函数
if (this->pObj != NULL) {
delete pObj;
pObj = NULL;
}
}
//成员函数:重载指针指向运算符->
//返回目标类指针类型
Object* operator->() {
return this->pObj;
}
//成员函数:重载解引用运算符*
//返回目标类对象引用类型,减少拷贝构造函数的开销
Object& operator*() {
return *(this->pObj);
}
};
int main(){
/*
//在堆区创建目标类的对象
Object* pObj = new Object(10);
pObj->func();
(*pObj).func();
//delete pObj; //若未显式释放,则会导致堆区内存泄露
*/
//在堆区创建目标类的匿名对象,并将堆区地址(对象指针)传递给栈区的智能指针类对象
//栈区的智能指针类对象在调用完毕后释放,会自动调用目标类的析构函数,释放堆区内存,无需显式delete
SmartPointer sp(new Object(10));
//sp->返回pObj,pObj->func()等价于sp->->func(),编译器内部会将 ->-> 简化为 ->。
sp->func(); //本质为sp->->func();
(*sp).func();
return 0;
}
输出:
/*
Object目标类的有参构造函数被调用
私有成员field = 10
私有成员field = 10
*/
Object目标类的有参构造函数被调用
SmartPointer智能指针类的有参构造函数被调用
私有成员field = 10
私有成员field = 10
SmartPointer智能指针类的析构函数被调用
Object目标类的析构函数被调用
8 不可重载逻辑与(&&)、逻辑或(||)运算符
逻辑与和逻辑非运算符具有短路特性,不可重载逻辑与(&&)(operator&&
函数)、逻辑或(||)运算符(operator||
函数)。
9 运算符重载总结
(1)<<
、>>
只能通过全局函数配合友元函数
进行重载;
(2)=
、[]
、()
、->
只能通过成员函数进行重载;
(3)不可重载逻辑与&&
、逻辑或||
运算符,可能无法实现短路特性。
注:左移运算符
<<
和右移运算符>>
通过全局函数重载,其余运算符均通过成员函数重载。
使用建议:
运算符 | 用法 |
---|---|
全部一元运算符 | 成员函数 |
= 、[] 、() 、-> 、-> 及* | 必须成员函数 |
+= 、-= 、/= 、*= 、^= 、&= 、!= 、%= 、>>= 、<<= | 成员函数 |
其它二元运算符 | 非成员函数 |
10 运算符重载练习:C++字符串类封装
C++中提供字符串类string
,支持等号赋值=
、加法运算+
、追加函数append()
等操作,方便字符串操作,其底层维护C语言的字符数组,实现对字符数组的各类操作。
通过字符数组实现字符串拷贝的步骤:
(1)在堆区开辟新的内存空间,存储原字符串所有字符
’和'\0'结束符
,并返回指向堆区字符数组的指针。
字符串长度:通过strlen函数
根据字符数组指针,获取字符串长度(不含'\0'结束符
)。
char *dest = new char[strlen(src) + 1];
strlen
函数原型:unsigned int strlen(const char *pStr);
(2)字符串拷贝:通过strcpy函数
将含有'\0'结束符
的源字符串复制新开辟的内存空间,返回类型为char*
。
strcpy(dest, src);
strcpy
函数原型:char* strcpy(char* dest, const char* src);
字符串操作的其它相关函数:
(3)字符串比较strcmp函数
:str1=str2返回0;str1<str2返回负数;str1>str2返回正数。
strcmp
函数原型:int strcmp(const char *str1, const char *str2)
(4)字符串拼接strcat函数
:将src源字符串(包括结束符“\0”)复制到dest目标字符串后(删除dest末尾的结束符“\0”)。
strcat
函数原型:extern char* strcat(char *dest, const char *src);
注1:需保证
*dest
目标字符串的内存空间足够大,可容纳被复制进来的*src
源字符串。
注2:src源字符串中的原有字符不变(限定为只读状态),返回指向dest目标字符串的指针。
(5)内存初始化memset函数
:将某块内存中的内容全部设置为指定值。将指针或数组对应的内存空间,全部初始化为指定值ch
(指针或数组的内存大小为count
)。
memset
函数原型:extern void* memset(void *buffer, int ch, int count);
练习:通过运算符重载模拟字符串类MyString类。
(1)成员属性
①维护堆区字符数组的指针:char* pStr;
②字符串长度:int length;
(2)成员函数
①无参构造函数
②有参构造函数
③拷贝构造函数
④析构函数
⑤成员函数-重载等号赋值运算符=
:使用深拷贝解决浅拷贝问题
⑥成员函数-重载索引中括号[]
:访问或修改指定索引位置的字符
⑦成员函数-重载加法运算符+
:字符串拼接
⑧成员函数-重载关系运算符==
:比较自定义的数据类型(自定义字符串类)
(3)全局函数(配合友元,访问类的私有成员)
①重载左移运算符<<
:(连续)输出自定义的数据类型(自定义字符串类)
②重载右移运算符>>
:(连续)输入自定义的数据类型(自定义字符串类)
MyString类头文件:myString.h
#pragma once //防止头文件被重复包含
#include <iostream>
using namespace std;
/* 模拟字符串类 */
//头文件包含:成员属性、成员函数的声明
class MyString {
//全局函数作友元,访问类的私有成员
friend ostream& operator<<(ostream& cout, MyString& str);
friend istream& operator>>(istream& cout, MyString& str);
private:
char* pStr; //底层维护指向堆区开辟的字符数组的指针
int length; //字符串长度(不计算\0)
public:
//无参构造函数
//MyString str;
MyString();
//有参构造函数
//MyString str = "Hello";
MyString(const char* src);
//拷贝构造函数
//MyString str2(str); 或 MyString str2 = str;
MyString(const MyString& str);
//析构函数
~MyString();
//成员函数:重载等号赋值运算符,支持连续赋值
MyString& operator=(const char* str);
MyString& operator=(const MyString &str);
//成员函数:重载[],支持索引访问
char& operator[](int pos);
//成员函数:重载加法运算符,支持自定义数据类型相加
//MyString str3 = str1 + str2;
MyString operator+(const MyString& str);
//MyString str3 = str1 + "abc";
MyString operator+(const char* str);
//成员函数:重载关系运算符==,比较自定义数据类型
bool operator==(const MyString& str);
bool operator==(const char* str);
};
MyString类源文件:myString.cpp
#define _CRT_SECURE_NO_WARNINGS //屏蔽strcpy函数的不安全告警
#include "myString.h"
//全局函数:重载左移<<运算符,配合友元访问类中私有成员
ostream& operator<<(ostream& cout, MyString& str) {
cout << str.pStr; //全局函数作友元,访问私有成员
return cout; //返回全局唯一的cout对象
}
//全局函数:重载右移>>运算符,配合友元访问类中私有成员
istream& operator>>(istream& cout, MyString& str) {
//先判断堆区是否存在数据,若有需先清空
if (str.pStr != NULL) { //全局函数作友元,访问私有成员
delete[] str.pStr;
str.pStr = NULL;
}
//将输入数据先存入栈区的字符数组(缓冲区),再拷贝至堆区
char buffer[1024] = { 0 };
cin >> buffer;
str.pStr = new char[strlen(buffer) + 1];
strcpy(str.pStr, buffer);
str.length = strlen(buffer);
return cin; //返回全局唯一的cin对象
}
//无参构造函数(形参:空参)
MyString::MyString()
{
//cout << "调用MyString类的无参构造函数" << endl;
//在堆区新开辟字符数组,数组长度为strlen(str) + 1
this->pStr = new char[1];
//strcpy函数实现字符串拷贝
strcpy(this->pStr, "");
//成员属性赋值:字符串长度
this->length = 0;
}
//有参构造函数(形参:字符数组指针)
MyString::MyString(const char* src)
{
//cout << "调用MyString类的有参构造函数" << endl;
//在堆区新开辟字符数组,数组长度为strlen(str) + 1
this->pStr = new char[strlen(src) + 1];
//strcpy函数实现字符串拷贝
strcpy(this->pStr, src);
//成员属性赋值:字符串长度
this->length = strlen(src);
}
//拷贝构造函数(形参:对象)
MyString::MyString(const MyString& str)
{
//cout << "调用MyString类的拷贝构造函数" << endl;
//在堆区新开辟字符数组,数组长度为strlen(str) + 1
this->pStr = new char[strlen(str.pStr) + 1];
//strcpy函数实现字符串拷贝
strcpy(this->pStr, str.pStr);
//成员属性赋值:字符串长度
this->length = strlen(str.pStr);
}
//析构函数
MyString::~MyString()
{
if (this->pStr != NULL) {
//cout << "调用MyString类的析构函数" << endl;
delete[] this->pStr; //释放字符数组的指针
this->pStr = NULL;
}
}
//成员函数:重载等号赋值运算符,支持连续赋值【情况1】
MyString& MyString::operator=(const char* str)
{
//先判断当前字符数组是否为空
if (this->pStr != NULL) {
delete[] this->pStr;
this->pStr = NULL;
}
//深拷贝赋值
this->pStr = new char[strlen(str) + 1];
strcpy(this->pStr, str);
this->length = strlen(str);
//返回当前对象,支持连续等号赋值
return *this;
}
//成员函数:重载等号赋值运算符,支持连续赋值【情况2】
MyString& MyString::operator=(const MyString& str)
{
//先判断当前字符数组是否为空
if (this->pStr != NULL) {
delete[] this->pStr;
this->pStr = NULL;
}
//深拷贝赋值
this->pStr = new char[strlen(str.pStr) + 1];
strcpy(this->pStr, str.pStr);
this->length = strlen(str.pStr);
return *this;
}
//成员函数:重载索引访问([])
char& MyString::operator[](int pos)
{
//返回当前字符数组指定索引上的字符
return this->pStr[pos];
}
//成员函数:重载加法运算符,支持自定义数据类型相加【情况1】
MyString MyString::operator+(const MyString& str)
{
//计算字符串拼接后,所需堆区内存空间
int size = this->length + strlen(str.pStr) + 1;
char* temp = new char[size];
//将堆区内存清零(初始化)
memset(temp, 0, size);
//依次拼接字符串
strcat(temp, this->pStr);
strcat(temp, str.pStr);
//根据堆区字符数组,创建MyString类对象
MyString newStr(temp);
//释放堆区字符数组,避免堆区内存泄露
delete[] temp;
//返回MyString类对象
return newStr;
}
//成员函数:重载加法运算符,支持自定义数据类型相加【情况2】
MyString MyString::operator+(const char* str)
{
//计算字符串拼接后,所需堆区内存空间
int size = this->length + strlen(str) + 1;
char* temp = new char[size];
//将堆区内存清零(初始化)
memset(temp, 0, size);
//依次拼接字符串
strcat(temp, this->pStr);
strcat(temp, str);
//根据堆区字符数组,创建MyString类对象
MyString newStr(temp);
//释放堆区字符数组,避免堆区内存泄露
delete[] temp;
//返回MyString类对象
return newStr;
}
//成员函数:重载关系运算符==,比较自定义数据类型【情况1】
bool MyString::operator==(const MyString& str)
{
return (strcmp(this->pStr, str.pStr) == 0) ? true : false;
}
//成员函数:重载关系运算符==,比较自定义数据类型【情况2】
bool MyString::operator==(const char* str)
{
return (strcmp(this->pStr, str) == 0) ? true : false;
}
测试程序:main.cpp
#define _CRT_SECURE_NO_WARNINGS //屏蔽strcpy函数的不安全告警
#include <iostream>
using namespace std;
#include "myString.h"
//重载左移运算符测试
void func1() {
MyString str1 = "Hello";
MyString str2 = str1;
//需重载左移运算符,输出自定义字符串MyString对象
cout << "str1 = " << str1 << endl;
cout << "str2 = " << str2 << endl;
}
//重载右移运算符测试
void func2() {
/*
char buff[64] = {0};
char buff2[64] = {0};
//cin支持链式编程
cin >> buff >> buff2;
cout << buff << endl;
cout << buff2 << endl;
*/
MyString str = "Hello";
cout << "对str重新赋值" << endl;
cin >> str;
cout << "新赋值后的str = " << str << endl;
}
//重载等号赋值运算符测试
void func3() {
MyString str1;
MyString str2;
str1 = str2 = "abc";
cout << "str1 = " << str1 << endl;
cout << "str2 = " << str2 << endl;
}
//重载索引访问([])测试
void func4() {
MyString str = "abc";
cout << "str[1] = " << str[1] << endl;
cout << "修改前的str = " << str << endl;
str[1] = 'a';
cout << "修改后的str = " << str << endl;
}
//重载加法运算符测试
void func5() {
MyString str1 = "abc";
MyString str2 = "def";
MyString str3 = str1 + str2;
cout << "拼接后的str3 = " << str3 << endl;
MyString str4 = str1 + "def";
cout << "拼接后的str4 = " << str4 << endl;
}
//重载关系运算符==测试
void func6() {
MyString str1 = "hellow";
MyString str2 = "hello";
cout << "str1 == str2:" << (str1 == str2) << endl;
cout << "str1 == \"hello\":" << (str1 == "hello") << endl;
}
int main() {
//func1();
//func2();
//func3();
//func4();
//func5();
func6();
return 0;
}