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

从上一篇文章一中,我们提到过编写的类分为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;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值