您的位置:首页 > 其它

编写类String的构造函数、析构函数和赋值函数(2)

2017-07-20 12:32 447 查看

编写类String的构造函数、析构函数和赋值函数。重载输出运算符。

class String
{
public:
String(const char *str = NULL); // 普通构造函数
String(const String &other); // 拷贝构造函数
~ String(void); // 析构函数
String & operator =(const String &other); // 赋值函数
private:
char *m_data; // 用于保存字符串
};


当类中包括指针类成员变量时,一定要重载其拷贝构造函数、赋值函数和析构函数。实现如下:

//普通拷贝函数
mystring::mystring(const char*str)
{
if (str == nullptr)
{
m_data = new char[1];
if (m_data != nullptr)
*m_data = '\0';
else
return;
}
else
{
int length = strlen(str);
m_data = new char[length + 1];
if (m_data != nullptr)
strcpy_s(m_data, (length+1), str);
else
return;
}
}
//拷贝构造函数
mystring::mystring(const mystring &o)
{
int length = strlen(o.m_data);
m_data = new char[length + 1];
if (m_data != nullptr)
strcpy_s(m_data, (length+1), o.m_data);
else
return;
}
//析构函数。
//若不重载,在析构时指针作为内在类型自动销毁,但实际内存不会。因此需要重新定义析构函数。
//一般地,重载析构函数意味着也需要一个拷贝构造函数和一个拷贝赋值运算符。见《c++ primer》P447。
mystring::~mystring(void)
{
delete[] m_data;
}
//拷贝赋值运算符
mystring & mystring::operator=(const mystring &o)
{
if (this == &o)
return *this;

delete [] m_data;
int length = strlen(o.m_data);
m_data = new char[length + 1];
if (m_data != nullptr)
{
strcpy_s(m_data, (length + 1), o.m_data);
return *this;
}
}


重载输出运算符

class mystring {
public:
/*和上述相同*/
friend ostream & operator<<(ostream &os, const mystring &ms);
//ostream & operator<<(ostream &os);
//上式等价于 ostream & operator<<(this, ostream &os);
//如下形式提示参数过多;
//ostream & operator<<(ostream &os, const mystring &ms);
void print() { cout << this->m_data; }
private:
char *m_data;
};


《c++ primer》P494曾讨论过重载输出运算符。在这里实现下。

1、当我在类的成员函数中加上:

ostream & operator<<(ostream &os, const mystring &ms);


提示参数过多。因为是成员函数,所以隐式地会在参数列表中加上this指针。

于是我改成:

ostream & operator<<(ostream &os);
//等价于 ostream & operator<<(this, ostream &os);


测试语句写成:

a<<(cout);


正常输出没问题。但从字面直观上这样是不对的。

再看书方明白作者们的讨论很有道理的。应该把函数定义为普通的非成员函数。如下:

ostream & operator<<(ostream &os, const mystring &ms)
{
os << ms.m_data;
return os;
};


因为要访问私有成员,所以声明为友元即可。

class mystring {
public:
/*其余相同*/
friend ostream & operator<<(ostream &os, const mystring &ms);
}


再测试如下:

cout << a;


输出正常,符合直观。彼时还有点小疑惑。为什么这样写就可以调用上述函数呢?形式不是很一致啊。

cout << a;
ostream & operator << (ostream &os, const mystring &ms);


查阅P490发现:

对于二元运算符来说,左侧运算对象传递给第一个参数,右侧运算符对象传递给第二个参数。

这就对了。当我们写成:

cout << a;


实际调用形式为:

<<(cout, a);


自然能够和

ostream & operator<< (ostream &os, const mystring &ms);


所匹配。OK。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: