Class with pointer members(Class String)
1. 测试代码(使用效果)
int main()
{
String s1(),
String s2("hello"); //构造函数
String s3(s1); //拷贝构造
cout << s3 << endl;
s3 = s2; //拷贝赋值
cout << s3 << endl;
}
2. Big Three 三种特殊函数
编译器默认的拷贝构造和拷贝复制不适用于包含指针的类,所以要自己写
class String
{
public:
String(const char* cstr = 0);
String(const String& str); //参数为相同类型对象的引用,拷贝构造
String& operator=(const String& str); //拷贝赋值
~String() //析构函数
char* get_c_str() const{
return m_data;
}
private:
char* m_data;
};
2.1 ctor & dtor(构造与析构)
inline
String::String(const char* cstr = 0)
{
if(cstr){
m_data = new char[strlen(cstr)+1]; //用new动态分配大小
strcpy(m_data,cstr);
}
else{ //未指定长度
m_data = new char[1];
*m_data = '\0';
}
}
inline
String::~String()
{
delete[] m_data;
}
2.2 Class with pointer members必须有copy ctor(拷贝构造)和copy op(拷贝赋值)
浅拷贝
浅拷贝.jpg
深拷贝
inline
String::String(const String& str){
m_data = new char[strlen(str.m_data) + 1]; //直接取得另一个对象的private数据
//可用友元解释
strcpy(m_data, str.m_data);
}
拷贝赋值函数
思路:若右边拷贝到左边,步骤为 清空左边;分配与右边相同空间;完成拷贝。
inline
String& String::operator=(const String& str){
if(this == &str){ //检测自我赋值,不仅仅是效率问题
return *this; // 如果不检验的话,可能造成行为未定义,见下图解释
}
delete[] m_data; // 清除左边
m_data = new char[ strlen(str.m_data) + 1];//开辟空间
strcpy(m_data, str.m_data); //完成拷贝
return *this
}
拷贝赋值.jpg
3. 重载<<操作符
按照通常的用法,cout<<s,所以不能重载为成员函数(要不然使用不便),就用全局重载好了
ostream& operator<<(ostream& os, const String str)
{
os << str.get_c_str();
return os;
}
总结:有指针变量的类,一定要重新其拷贝构造,拷贝赋值和析构函数!
网友评论