编写类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。
相关文章推荐
- 编写类String的构造函数、析构函数和赋值函数(转载)
- 编写String 类的构造函数,析构函数和赋值函数
- 编写类String的构造函数、析构函数和赋值函数
- 详解C++ 编写String 的构造函数、拷贝构造函数、析构函数和赋值函数
- 编写类String的构造函数、析构函数和赋值函数
- 编写类String的构造函数、析构函数和赋值函数
- 编写类String 的构造函数、析构函数和赋值函数
- 编写类String的构造函数,析构函数和赋值函数
- 编写类String的构造函数、析构函数和赋值函数
- 编写类String的构造函数、析构函数和赋值函数
- 编写类string的构造函数、析构函数和赋值函数
- 编写类String的构造函数、析构函数和赋值函数
- 编写类String的构造函数、析构函数和赋值函数
- 编写类String的构造函数、析构函数和赋值函数
- 编写类 String 的构造函数、析构函数和赋值函数
- 编写类String的构造函数、析构函数和赋值函数
- 编写类String的构造函数、析构函数和赋值函数
- 编写类String 的构造函数、析构函数和赋值函数
- 编写类String的构造函数、析构函数和赋值函数
- 编写类String的构造函数、析构函数和赋值函数