从String类看写C++ class需要注意的地方

 

 

// 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;    
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值