String.h
#pragma once
#include <iostream>
#include <cstring>
//******************************************************
// 问题1:类中数据成员中含有指针类型 处理方式--必须要有拷贝构造
//******************************************************
//******************************************************
// 1 要明白string 其实就是包装好了的char[n], (字符串数组)
// 2 深浅拷贝问题:开空间,拷数据!
//******************************************************
class String
{
private:
// 数据成员
char* str;
size_t length;
public:
// 默认构造函数:
String() = default;
// String a{"hello"} ---- 构造
String(const char* str_)
{
if (str_ != nullptr)
{
// 这里是字符串和字符串数组的区别:'\0'
length = strlen(str_) + 1;
// 开空间,拷数据:(有地址,有数据才叫拷贝)
str = new char[length];
strcpy_s(str, length, str_); // 字符串的拷贝
}
else
{
// 空字符串要为'\0'申请内存:
str = new char[1];
length = 0;
str[0] = '\0';
}
}
// 拷贝构造函数:
String(const String& obj)
{
// 开空间,拷数据:(深拷贝)
length = strlen(obj.str) + 1;
str = new char[length];
strcpy_s(str, length, obj.str);
std::cout <<"进入拷贝构造函数\n" <<str;
// 浅拷贝:str = obj.str; strcpy_s(str,length,boj,str); 没有重新开辟空间,两个对象指向同一个空间,释放时出错
}
// 赋值构造函数:(也可以返回引用,但是不能用temp了,因为引用不会建立临时缓存)
// 必须返回引用,为了可以连续的赋值
String& operator=(const String& obj)
{
if (this != &obj)
{
// 赋值之前 析构原本的内存。
delete[] str;
str = nullptr;
str = new char[strlen(obj.str) + 1];
strcpy_s(str, strlen(obj.str) + 1, obj.str);
}
return *this;
}
~String()
{
delete[]str;
str = nullptr;
}
public:
char* getStr()const
{
return this->str;
}
};
验证代码:
// 重新写。
#include <iostream>
#include "String.h"
using namespace std;
int main()
{
String objA; // 默认构造函数
String objB{ "hello world" };
// 拷贝构造函数:
String objC{ objB };
赋值构造函数:
String objD = "baby";
String objE = "money"; // 其实这里等于:String objE=String temp{money};
objA = objE;
// 测试不可变对象问题。3个条件:1数据成员全部私有;2没有set函数;3get函数不能返回指针。
cout << objB.getStr() << endl;
cout << objD.getStr() << endl;
// 在外部修改了私有数据成员。
strcpy_s(objB.getStr(), 5, objD.getStr());
cout << objB.getStr() << endl;
cout << objA.getStr() << endl;
String objF{ nullptr };
return 0;
string a;
}