从String类看写C++ class需要注意的地方
时间:2010-08-03 来源:chengbin_liu
String.h的定义:
#include <string.h> //strlen, strcpy等C字符串处理函数
#include <iostream> using namespace std;
class String
{
public:
String(const char* p=NULL) // 构造函数
{
if(p==NULL) // String str; //将构造一个长度为0的空字符串""
{
data = new char[1]; // 构造对象的三种方式(指定实参的方式):
*data = '\0'; // String s1("hello"); // 第1种,常用的,推荐的
size = 0; // String s2 = "hello"; // 第2种,只适用与单个实参。
} // String s3 = String("hello"); // 第3种,很少见
else
{
size = strlen(p);
data = new char[size+1]; // 注意需要+1,存放'\0'
strcpy(data,p);
}
}; String(const String& str) // 拷贝构造函数,如下构造String对象时会调用:
{ // String s1 = "hello";
size = str.size; // String s2(s1); // 调用拷贝构造函数
data = new char[size+1]; // String s3 = s1;// 调用拷贝构造函数
strcpy(data,str.data); // String s4;
}; // s4 = s1; //不会调用拷贝构造函数,而是调用operator= String& operator = (const String& other) // 赋值操作符
{ // 如果省略,需要时,会调用缺省的operator=。但本类不能省略,因为存在char*的成员。
if(this != &other) // 注意自赋值!!
{ // 如果省略该operator=,以下代码将是灾难性的:
delete[] data; // String s1 = "hello";
size = other.size; // String s2;
data = new char[size+1];// s2 = s1;//调用缺省的operator=,data指向同一片内存
strcpy(data,other.data);// 如果也没有char*的operator=的话,以下代码也有同样问题
} // String s1;
return *this; // s1 = "hello"; //先构造临时对象,再调用缺省的String的operator=
}; // 该问题,详细可以参考:EffectiveC++ item11 String& operator = (const char* p)
{ // char* 的operator=
delete[] data; // 在如下代码时会调用
if(p==NULL) // String s1;
{ // s1 = "hello";
data = new char[1]; // 如果没有该operator=,s1 = "hello"会先根据"hello"构造临时对象,
*data = '\0'; // 然后再调用String的operator=(自定义或缺省的)赋值给s1
size = 0; // 可以用explicit关键字修饰const char*的构造函数禁止此隐式转换
} // 但要注意下面这条语句是不会调用该operator=,而是调用构造函数:
else // String s1 = "hello";
{
size = strlen(p);
data = new char[size+1];
strcpy(data,p);
}
return *this; // 注意返回值为String&,为了链式表达,如:s2 = s1 = "hello";
} bool operator == (const String& other)
{
if(this == &other)
{
return true;
}
else
{
return strcmp(data,other.data) == 0;
}
}
~String(void)
{
if(data != NULL)
{
delete[] data; // 注意数组的delete形式!!!
}
}; // operator<<重载,该操作符的重载必须定义为命名空间函数,不能定义为该类的成员函数。
// 因为:只有在左left 操作数是该类类型的对象时才会考虑使用作为类成员的重载操作符。
// 而<<左操作数是ostream,所以不能使用类成员函数。
// 为了该非类成员函数能够访问String的私有成员,故在次声明为该类的友元函数。
friend ostream& operator << (ostream& out, const String& str);
private:
char* data;
int size; };
// String.cpp的实现:
#include ".\String.h" // String的operator<<的定义。
ostream& operator << (ostream& out, const String& str)
{ // 因为已经声明了String的friend函数,故可以直接使用String的private成员data
out<<str.data; // 否则需要在String中定义一个public的函数获取数据
return out;
}
#include <string.h> //strlen, strcpy等C字符串处理函数
#include <iostream> using namespace std;
class String
{
public:
String(const char* p=NULL) // 构造函数
{
if(p==NULL) // String str; //将构造一个长度为0的空字符串""
{
data = new char[1]; // 构造对象的三种方式(指定实参的方式):
*data = '\0'; // String s1("hello"); // 第1种,常用的,推荐的
size = 0; // String s2 = "hello"; // 第2种,只适用与单个实参。
} // String s3 = String("hello"); // 第3种,很少见
else
{
size = strlen(p);
data = new char[size+1]; // 注意需要+1,存放'\0'
strcpy(data,p);
}
}; String(const String& str) // 拷贝构造函数,如下构造String对象时会调用:
{ // String s1 = "hello";
size = str.size; // String s2(s1); // 调用拷贝构造函数
data = new char[size+1]; // String s3 = s1;// 调用拷贝构造函数
strcpy(data,str.data); // String s4;
}; // s4 = s1; //不会调用拷贝构造函数,而是调用operator= String& operator = (const String& other) // 赋值操作符
{ // 如果省略,需要时,会调用缺省的operator=。但本类不能省略,因为存在char*的成员。
if(this != &other) // 注意自赋值!!
{ // 如果省略该operator=,以下代码将是灾难性的:
delete[] data; // String s1 = "hello";
size = other.size; // String s2;
data = new char[size+1];// s2 = s1;//调用缺省的operator=,data指向同一片内存
strcpy(data,other.data);// 如果也没有char*的operator=的话,以下代码也有同样问题
} // String s1;
return *this; // s1 = "hello"; //先构造临时对象,再调用缺省的String的operator=
}; // 该问题,详细可以参考:EffectiveC++ item11 String& operator = (const char* p)
{ // char* 的operator=
delete[] data; // 在如下代码时会调用
if(p==NULL) // String s1;
{ // s1 = "hello";
data = new char[1]; // 如果没有该operator=,s1 = "hello"会先根据"hello"构造临时对象,
*data = '\0'; // 然后再调用String的operator=(自定义或缺省的)赋值给s1
size = 0; // 可以用explicit关键字修饰const char*的构造函数禁止此隐式转换
} // 但要注意下面这条语句是不会调用该operator=,而是调用构造函数:
else // String s1 = "hello";
{
size = strlen(p);
data = new char[size+1];
strcpy(data,p);
}
return *this; // 注意返回值为String&,为了链式表达,如:s2 = s1 = "hello";
} bool operator == (const String& other)
{
if(this == &other)
{
return true;
}
else
{
return strcmp(data,other.data) == 0;
}
}
~String(void)
{
if(data != NULL)
{
delete[] data; // 注意数组的delete形式!!!
}
}; // operator<<重载,该操作符的重载必须定义为命名空间函数,不能定义为该类的成员函数。
// 因为:只有在左left 操作数是该类类型的对象时才会考虑使用作为类成员的重载操作符。
// 而<<左操作数是ostream,所以不能使用类成员函数。
// 为了该非类成员函数能够访问String的私有成员,故在次声明为该类的友元函数。
friend ostream& operator << (ostream& out, const String& str);
private:
char* data;
int size; };
// String.cpp的实现:
#include ".\String.h" // String的operator<<的定义。
ostream& operator << (ostream& out, const String& str)
{ // 因为已经声明了String的friend函数,故可以直接使用String的private成员data
out<<str.data; // 否则需要在String中定义一个public的函数获取数据
return out;
}
相关阅读 更多 +