以前没有把类搞得很清楚,后来慢慢摸索了一下才弄懂一些了,顺便发出来,以后忘记了或者有新认识的时候可以再学习!!!
题目:
1.<<、>>运算符重载模板
friend ostream& operator<<(ostream& cout, CMyString& str);
friend istream& operator>>(istream& cin, CMyString& str);
2.+、=、==运算符重载模板
CMyString/void/bool operator+/=/==(const CMyString& str/const char* str);
注意:返回值是啥就返回相应的东西,运算符左边为CMyString类型,右边为括号对应的类容(类/字符串)
3.#define _CRT_SECURE_NO_WARNINGS
严重性 代码 说明 项目 文件 行 禁止显示状态
错误 C4996 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. Project1 D:\2022_12_12REINOVO_16th\1212测试\运算符重载案例\Project1\MyString.cpp 27
我在CMyString.h里定义了#define _CRT_SECURE_NO_WARNINGS,如果没有定义vs2022(似乎vs1017以上都会这样)会提示我们一些函数使用不安全,比如strcpy/strcat这些函数,当我们定义了_CRT_SECURE_NO_WARNINGS之后,就考虑弃用禁用了strcpy_s/strcat_s一系列函数,则没有报错了。
4.关于堆区内存的处理,我们之所以会在堆区开辟内存,主要原因还是堆区可以存放更大内存的数据,但是用堆区必须要手动释放,如果用了char*p=new char[len],那就要delete[] p;p=NULL;去释放;又或者用malloc,需要用free()释放。栈区会自动释放内存。
以上就是我主要解决的一些问题,以下是完整代码可以直接跑!!!
//CMyString.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS//考虑禁用弃用了strcat_s等一系列函数
#include <iostream>
using namespace std;
class CMyString
{
//<<和>>的重载,友元函数的运用(似乎ostream&和istream&可以写作ostream和istream)
friend ostream& operator<<(ostream& cout, CMyString& str);
friend istream& operator>>(istream& cin, CMyString& str);
public:
//CMyString A="123456"或者CMyString A("123456")
CMyString(const char* str);
//CMyString A(A0)
CMyString(const CMyString& str);
//CMyString A
CMyString();
//如果int m_size;是私有变量,那么就可以运用这个成员函数求长度
int Length();
//+号的运算符重载
CMyString operator+(const char* str);//(CMyString)A+"123"满足
CMyString operator+(const CMyString& str);//(CMyString)A+(CMyString)A0满足
//=号的运算符重载,我们从=号左边的类的指针去改变其内部的值,可以用void不用返回任何值
void operator=(const CMyString& str);
void operator=(const char* str);
//==运算符的重载,注意:这里==有字符串时和类字符串左右交换位置后需要另一个重载函数
bool operator==(const CMyString& str);
bool operator==(const char* str);
//bool operator==(const CMyString& str); //但是暂时写不出const char和类交换后的比较
//[]的重载
char& operator[](int index);
//c_str()
const char* C_str();
public:
~CMyString();//析构函数总是先析构离自己最近的一个变量
private:
char* Pstring;
int m_size;
};
//CMyString.cpp
#include "CMyString.h"
CMyString::CMyString(const char *str)
{
this->Pstring = new char[strlen(str) + 1];
strcpy(this->Pstring, str);
this->m_size = strlen(str);
}
CMyString::CMyString(const CMyString& str)
{
this->Pstring = new char[strlen(str.Pstring) + 1];
strcpy(this->Pstring, str.Pstring);
this->m_size = str.m_size;
}
//定义一个空的构造函数
CMyString::CMyString()
{
this->Pstring = NULL;
this->m_size = 0;
}
//访问自身的长度
int CMyString::Length()
{
int len=this->m_size;
return len;
}
CMyString CMyString::operator+(const char* str)
{
int newLen = this->m_size + strlen(str) + 1;
char* newStr = new char[newLen];
memset(newStr, 0, newLen);
strcat(newStr, this->Pstring);
strcat(newStr, str);
CMyString A(newStr);
delete[] newStr;
newStr = NULL;
return A;
}
CMyString CMyString::operator+(const CMyString& str)//*不能写作&,&代表一个地址,而*代表指针
{
int newLen = this->m_size + strlen(str.Pstring) + 1;
char* newStr = new char[newLen];
memset(newStr, 0, newLen);
strcat(newStr, this->Pstring);
strcat(newStr, str.Pstring);
CMyString A(newStr);
delete[] newStr;
return A;
}
void CMyString::operator=(const CMyString& str)
{
if (this->Pstring != NULL)
{
delete[] this->Pstring;
this->Pstring = NULL;
}
int newLen = str.m_size + 1;
this->Pstring = new char[newLen];
memset(this->Pstring, 0, newLen);
strcpy(this->Pstring, str.Pstring);
this->m_size = str.m_size;
//若我们不用void而用CMyString,那可以return *this;
}
void CMyString::operator=(const char* str)
{
if (this->Pstring != NULL)
{
delete[] this->Pstring;
this->Pstring = NULL;
}
int newLen = strlen(str) + 1;
this->Pstring = new char[newLen];
memset(this->Pstring, 0, newLen);
strcpy(this->Pstring, str);
this->m_size = strlen(str);
}
bool CMyString::operator==(const CMyString& str)
{
if (strcmp(this->Pstring, str.Pstring)==0 && (this->m_size == str.m_size))
return true;
return false;
}
bool CMyString::operator==(const char* str)
{
if (strcmp(this->Pstring, str)==0 && (this->m_size == strlen(str)))
return true;
return false;
}
char& CMyString::operator[](int index)
{
return this->Pstring[index];
}
const char* CMyString::C_str()
{
const char* p;
p = this->Pstring;
return p;
}
CMyString::~CMyString()
{
if (this->Pstring != NULL)//这里的判断是考虑this->Pstring没有被赋值的影响
{
delete[] this->Pstring;
this->Pstring = NULL;
}
}
ostream& operator<<(ostream& cout, CMyString& str)
{
// TODO: 在此处插入 return 语句
cout << str.Pstring;
return cout;
}
istream& operator>>(istream& cin, CMyString& str)
{
//判断内容是否为空,不是则清空
if (str.Pstring != NULL)
{
delete[] str.Pstring;
str.Pstring = NULL;
}
//让用户输入内容
char newstr[1024];//栈内存最高为1024字节
cin >> newstr;
str.Pstring = new char[strlen(newstr) + 1];
strcpy(str.Pstring, newstr);
str.m_size = strlen(newstr);
return cin;
}
主程序:
// Project6.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束
#include <iostream>
#include"CMyString.h"
using namespace std;
void initialization()//关于对一块内存的初始化问题
{
char aa[100] = { 4 };//初始化并不等于给定了值,而是让内存里的地址不指向空
//初始化只是对第一个值赋值为括号内的值,往后所有数据全为0;
cout << aa[0] + 1 << endl;
int a2[100];//int类型的数只能初始化为0或者-1;
//原因是memset初始化是一个字节一个字节的赋值,当赋值为1时,实际初始化的值二进制为0001 0001 0001 0001,也就是16843009
memset(a2, 1, 100);//memset可以初始化为其他数
cout << a2[1] << endl;
}
void Go()
{
CMyString A0 = "123";
CMyString A1("456"); //A0和A1的构造函数一样都是 CMyString(const char* str);
CMyString A2(A1); //构造函数为 CMyString(const CMyString& str);
CMyString A3; //构造函数为 CMyString();
//<<和>>重载分析
cout << A0 << "\t" << A1 << endl; //输出123 456
//利用成员函数访问私有变量调用自身长度
cout << A0.Length() << endl; //输出 3
//+运算符重载
A3 = A0 + "123" + A1; //调用+重载函数后,再调用=重载函数
//"123"不能放到第一个位置,因为没有写这个重载方式
cout << "A3等于" << A3 << endl; //输出123456
CMyString A4 = A0 + "789";
cout << A4 << endl; //输出123789
//=运算符的重载
//A3 = A0 + A1;
//判断==符号重载
CMyString A5 = "456";
if (A1 == A5)
{
cout << "A1等于A5" << endl;
}
if (A0 == "123")
{
cout << "A0等于123" << endl;
}
//char& operator[](int index);[]的重载
CMyString A6[5];
A6[3] = "123456789";
cout << "A6[3]" << A6[3] << endl << "A6[3]长度为:" << A6[3].Length() << endl;
//A6[3]123456789
//A6[3]长度为:9
//C_str()的使用
CMyString A7 = "www";
const char* p;
p = A7.C_str();
cout << "A7改变前:" << endl;
cout << "A7:" << A7 << endl;
cout << "p:" << p << endl;
A7 = "aaa";
cout << "A7改变后:" << endl;
cout << "A7:" << A7 << endl;
cout << "p:" << p << endl; //很明显,A7改变后,p也改变了,p总是指向A7的地址
}
int main()
{
//关于一些初始化的问题
//initialization();
Go();
return 0;
}
若有不周之处,欢迎讨论。