您的位置:首页 > 编程语言 > C语言/C++

C++编程中类class的编写(二):含指针数据的类

2017-12-03 11:24 148 查看
从上一篇文章一中,我们提到过编写的类分为2种,在这里再对含指针数据的类来进行考量,对于含指针数据的类,必须要进行自己编写拷贝构造和拷贝赋值(为了防止浅拷贝也就是2个对象的指针数据指向同一块内存单元),同时也必须使用析构函数(对于指针进行了new或者malloc进行动态分配,必须回收资源),那么由此以编写简单的string类做一个总结:
class String{
private:
char* data;
public:
String(const char* ctr=0);//构造函数声明式
String(const String& rhs);//拷贝构造
String& operator = (const String& rhs);  //拷贝赋值
~String();//析构
};

对于一个含有指针的类,我们很理所当然的写出上面这样的类,有需要时再添加成员函数,那考虑一下为什么拷贝构造和拷贝赋值里的参数是const reference,传reference是为了快,提高效率,在这两个函数里面,我们传入的值当然是不希望被改变的,也是不需要改变的,只是把他的值给出去,那当然是const.

对构造函数进行编写:

inline
String::String(const char* ctr){
if(ctr){
data = new char[strlen(ctr)+1];
strcpy(data,ctr);
}
else{
data = new char[1];
*data = '\0';
}
}

我们发现这里编写的定义式和在类中的声明式不一样,当然这也是我在编译时发现了错误改正的,编译器提示既然在声明式中缺省赋值了ctr就不要再定义式中重复赋值,所以这里没有其值,当然inline还是要写,建议编译器去inline,能不能行看编译器处理。

紧接着函数会对要进行构造的初值进行判断,如果没有,就给出一个\0结束,有的话就取它的长度开辟空间(注意\0也需要给一个字节),然后字符串拷贝。

析构函数:inline
String::~String(){
delete[] data;
}这个函数很明白,释放自己分配的资源或者打开的文件,这里只有data开辟了内存空间所以释放data,开辟的时候是array new,释放的时候就使用array delete.
拷贝构造:inline
String::String(const String& rhs){
data = new char[strlen(rhs)+1];
strcpy(data,rhs);
}很简单,就是为了防止浅拷贝,所以分配内存,复制就可以。
拷贝赋值:inline
String& String::operator = (const String& rhs){
if(this == &rhs)
return *this;
delete[] data;
data = new char[strlen(rhs)+1];
strcpy(data,rhs);
return *this;
}这里主要有2个注意点,第一就是如果this和rhs指向了同一个地方,我们就不能直接把rhs删除,如果删除,那接着this去开辟空间的时候,我该拿什么值,不知道了,已经没有了,所以需要进行一个判断,防止程序出错。
第二就是我们会想拷贝赋值,我直接对this操作了,那this不就有值了么,还返回干嘛,是这样没错,但是我们经常会有一种用法就是s3=s2=s1="hello world";那这时候如果没有返回值,s2=s1时就会出错,s1拿void给s2?,很明显的如果我要成功使用上述语句,我需要返回一个值给下面的人用,当然你可以不返回,那用户就麻烦了,需要static_cast<String>这样强制类型转换,万一出错呢,接口要友好。

当然在这里我们也会考虑就是把string类输出的情况,这时候就要重载运算符<<,把它放入成员函数明显不合适,那我肯定需要一个传入的参数也就是右边的值,在<<右边我们通常放string,左边放ostream,在成员函数里面重载<<的话,我就需要传入ostream,那我写在程序里就会是s1 << cout,不符合日常习惯,所以一般就使用非成员函数了。

代码如下:inline
ostream& operator << (ostream* os,const String& rhs){
os << rhs.data;//错误了,在非成员函数里怎么能取对象的private,之前是同一类的所有对象可以看错friend
}所以这时候,我们需要在String类里面加一个获得private数据的成员函数,这也是为什么我说有需要的时候就要写。
class String{
...
char* get_data() const { return data;}
}用const函数是因为它不改变所有的值,这时候上面的运算符重载就可以写成os << rhs.get_data();成功获得数据,为什么返回的是ostream&,和上面考虑的是一个道理,一个是目的对象是一直存在内存的,所以可以用引用,返回ostream还是为了可以连续传出,比如cout << s1 << endl << s2 << endl;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: