文章目录
第一步:构建简单的构造函数和析构函数
class String
{
private:
char* str;
public:
String(char* p, int)
{
str = p;
}
//构造函数
String(const char* p = NULL) :str(NULL)
{
if (p != NULL)//要传的字符串不为空
{
//申请堆空间
str = new char[strlen(p) + 1];
strcpy_s(str, strlen(p) + 1, p);
}
else
{
str = new char[1];
*str = '\0';
}
cout << "Create String:" << this << endl;
}
//析构函数
~String()
{
if (str != NULL)
{
delete[]str;
}
str = NULL;
cout << "Destory String" << this << endl;
}
};
1.1 模拟输出(operator<<)
避免友元函数,需要在类外写一个输出函数
ostream& operator<<(ostream& out)const
{ //this->str
if (str != NULL)
{
out << str;
}
return out;
}
为了避免使用友元:在类外在定义再写一个输出函数:
ostream& operator<<(ostream& out,const String &s)
{ //类外没有this指针,需要在定义一个对象s
s << out; //<<调用类中的 s.operator<<()
return out;
}
int main()
{
String s{ "baiU" };
cout << s << endl;//直接调用输出运算符,输出对象
}
1.2 拷贝构造函数
String(const String& s)
{
//避免浅拷贝
str = new char[strlen(s.str) + 1];;
strcpy_s(str, strlen(s.str) + 1, s.str);
cout << "copy String" << this << endl;
}
int main()
{
String s{ "baiU" };
String s1(s);
}
1.3 赋值运算符重载
String& operator = (const String& s)
{
if (this != &s)
{
delete[]str;
str = new char[strlen(s.str) + 1];
strcpy_s(str, strlen(s.str) + 1, s.str);
}
cout << "operator =" << this << endl;
return *this;
}
注意点:防止自赋值,防止内存泄漏,防止浅拷贝
int main()
{
String s{ "baiU" };
String s1(s);
String s2{"shiqianyu"};
s2 = s;
}
1.4 加法运算符重载
因为返回时要构造一个对象,需要在重载一个构造函数,作为私有成员。
String(char* p, int)//int 占位符
{
str = p;
}
1.4.1对象和对象相加
String operator+(const String& s)
{
int len = strlen(str) + strlen(s.str) + 1;
char* p = new char[len];
strcpy_s(p, len, str);
strcat_s(p,len,s.str);
cout << "Object+object" << endl;
return String(p, 1);
}
1.4.2字符串和对象相加
String operator+(const char* p, const String& s)
{
cout << "char* + Object" << endl;
return String(p) + s;
}
int main()
{
String s{ "baiU" };
String s2{"shiqianyu"};
s = s + s2;
// s2 = "love" + s2;
String s3;
s3 = fun();
return 0;
}
1.5 移动构造函数
String(String&&s)
{
cout << "move construct:" << this<<endl;
str = s.str;
s.str = NULL;
}
1.6 移动赋值运算符重载在整个程序执行的过程中,只对堆内存空间new了一次,
String fun()
{
String s2("yangyu");
return s2;
}
```cpp
int main()
{
String s1; //调用默认构造申请对象空间
s1 = fun();
return 0;
}
String s1;
调用构造函数申请对象空间
2. String s2{yangyu};
调用构造函数,申请空间,创建对象,并对对象进行初始化。
3. return s2
调用移动构造函数,创建将亡值对象,并让将亡值对象指向s2.(str = s.str;
)。并把s2中str置为空(s.str = NULL;
)
4. 析构s2
5. s1 = fun() 调用Release()完成数据交换。 s.str = Release(s.str);·
重点:
- 首先s2调用构造函数完成对str的初始化,也就是s2指向为字符串“baiU”开辟的堆空间。
- return s2时,返回调用点处(调用的是移动构造函数)创建将亡值对象,指向 s2申请的空间,
- s2析构。
- 将亡值移动赋值给s1过程。
char* Release(char* p)
{
char* old = str;
str = p;
return old;
}
重点:
Release()函数实现了资源的交换,让s1指向s2申请的空间,将亡值指向s1申请的空间,函数结束。将亡值值被析构,s1成功拿到了原s2的资源,
//优先调用
String& operator = (String&&s)
{
if (this != &s)
{
s.str = Release(s.str); //将str = s.str 并将str原本的值释放掉。
}
cout << "operator =&&" << this << endl;
return *this;
}
完整代码:
class String
{
private:
char* str;
public:
String(char* p, int)
{
str = p;
}
//构造函数
String(const char* p = NULL) :str(NULL)
{
if (p != NULL)//要传的字符串不为空
{
//申请堆空间
str = new char[strlen(p) + 1];
strcpy_s(str, strlen(p) + 1, p);
}
else
{
str = new char[1];
*str = '\0';
}
cout << "Create String:" << this << endl;
}
//拷贝构造函数
String(const String& s)
{
//避免浅拷贝
str = new char[strlen(s.str) + 1];;
strcpy_s(str, strlen(s.str) + 1, s.str);
cout << "copy String" << this << endl;
}
//移动构造函数
String(String&&s)
{
cout << "move construct:" << this<<endl;
str = s.str;
s.str = NULL;
}
//析构函数
~String()
{
if (str != NULL)
{
delete[]str;
}
str = NULL;
cout << "Destory String" << this << endl;
}
//避免友元函数,需要在类外写一个输出函数
ostream& operator<<(ostream& out)const
{ //this->str
if (str != NULL)
{
out << str;
}
return out;
}
//赋值运算符重载
String& operator = (const String& s)
{
if (this != &s)
{
delete[]str;
str = new char[strlen(s.str) + 1];
strcpy_s(str, strlen(s.str) + 1, s.str);
}
cout << "operator =" << this << endl;
return *this;
}
char* Release(char* p)
{
char* old = str;
str = p;
return old;
}
//优先调用
String& operator = (String&&s)
{
if (this != &s)
{
s.str = Release(s.str); //将str = s.str 并将str原本的值释放掉。
}
cout << "operator =&&" << this << endl;
return *this;
}
//加法运算符重载
//对象和对象相加
String operator+(const String& s)
{
int len = strlen(str) + strlen(s.str) + 1;
char* p = new char[len];
strcpy_s(p, len, str);
strcat_s(p,len,s.str);
cout << "Object+object" << endl;
return String(p, 1);
}
};
String fun()
{
String s2("yangyu");
return s2;
}
ostream& operator<<(ostream& out,const String &s)
{ //类外没有this指针,需要在定义一个对象s
s << out; //<<调用类中的 s.operator<<()
return out;
}
String operator+(const char* p, const String& s)
{
cout << "char* + Object" << endl;
return String(p) + s;
}
int main()
{
// String s{ "baiU" };
// cout << s << endl;//直接调用输出运算符,输出对象s
// String s1(s);
// String s2{"shiqianyu"};
// s2 = s;
s = s + s2;
// s2 = "love" + s2;
String s3;
s3 = fun();
return 0;
}