C++编程中类class的编写(二):含指针数据的类
2017-12-03 11:24
148 查看
从上一篇文章一中,我们提到过编写的类分为2种,在这里再对含指针数据的类来进行考量,对于含指针数据的类,必须要进行自己编写拷贝构造和拷贝赋值(为了防止浅拷贝也就是2个对象的指针数据指向同一块内存单元),同时也必须使用析构函数(对于指针进行了new或者malloc进行动态分配,必须回收资源),那么由此以编写简单的string类做一个总结:
对于一个含有指针的类,我们很理所当然的写出上面这样的类,有需要时再添加成员函数,那考虑一下为什么拷贝构造和拷贝赋值里的参数是const reference,传reference是为了快,提高效率,在这两个函数里面,我们传入的值当然是不希望被改变的,也是不需要改变的,只是把他的值给出去,那当然是const.
对构造函数进行编写:
我们发现这里编写的定义式和在类中的声明式不一样,当然这也是我在编译时发现了错误改正的,编译器提示既然在声明式中缺省赋值了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;
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;
相关文章推荐
- 编写程序读入一组string类型的数据,并将它们存储在vector中,再将vector对象复制给一个字符指针数组。
- 在编写JSON数据时java.lang.ClassNotFoundException: org.apache.commons.lang.exception.NestableRuntimeExcepti
- C++编程中类CALSS的编写(一):不含指针数据的类
- Safe C++ 读书笔记:对基本数据类型进行封装,以编写更安全的C++代码
- 数据指针的学习以及地址的理解
- Robotium编写测试用例如何模拟Junit4的BeforeClass和AfterClass方法1 - 条件判断法
- Objective-C 2.0 with Cocoa Foundation--- 5,Class类型,选择器Selector以及函数指针
- C指针编程之道(三)- 数据结构中指针的应用
- 使用 SQL 语句创建 School 数据库(包括参数)、 TblClass 表、 TblStudent 表。 并向其中填入数据。
- 返回整型数据的指针int *p
- int (*p)[3]指向由整型数据组成的数组的指针
- Delphi class of (类引用, 指向类信息的指针)
- HBase数据迁移(3)-自己编写MapReduce Job导入数据
- 20130710发送UDP数据时出现空指针错误
- java 高新技术【10】 编写对class文件进行加密的工具类
- QVariant保存指针数据
- 编写一个程序,在E盘下创建一个abc.txt的文本文档,通过输出流在文档内添加数据,然后在把abc.txt复制到F盘下
- 使用指针比较整型数据的大小
- 指针数据和数组指针等问题
- 手动编写代码创建数据表