一个案例理解C++面向对象之运算符重载

时间:2021-08-13
本文章向大家介绍一个案例理解C++面向对象之运算符重载,主要包括一个案例理解C++面向对象之运算符重载使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

运算符重载是C++面向对象基础知识,本文通过一个自定义的string类完全理解运算符重载并且能够温习const与引用的相关知识:

  1. 首先构造一个字符串类,既然是字符串类,基本的两个属性应该是必需的:字符串和字符串长度
// String类的组成
class String
{
private:
    char* str;
    int len;
}
  1. 其次为了完成字符串的初始化需要定义构造函数,为了保证内存不泄露需要定义析构函数,为了保证深拷贝定义复制拷贝函数
class String
{
public:
    String();
    String(char* s);
    ~String();
    String(const String & s);
}
  1. 为了完成字符串的运算操作需要重载‘+’,‘*’,‘<<','>>'运算符
// 使用const成员函数实现右乘即“ str*3 <=> strstrstr ”的功能
    String operator*(int num) const;
// 使用成员函数实现赋值运算即“ String1 = String2 = "string" ”的功能
    String & operator=(const String & s);
// 使用成员函数实现中括号索引运算即“ String[1] ”的功能
    char & operator[](int num);
// 使用const成员函数实现常对象的中括号索引运算即“ String[1] ”的功能
    const char & operator[](int num) const;
// 使用友元函数重载实现左乘即“ 3*str <=> strstrstr ”的功能
    friend String operator*(int num,const String & s);
// 使用友元函数实现加法即“ str1+str2 <=> str1str2 ”的功能
    friend String operator+(const String & s1,const String & s2);
// 使用友元函数实现输出即“ cout<<str ”的功能
    friend std::ostream & operator<<(std::ostream & os,const String & s);
// 使用友元函数实现输入即“ cin>>str ”的功能
    friend std::istream & operator>>(std::istream & is,String & s);
  1. 为了保证自定义String类和字符串指针的等价转换需要定义转换函数
// 使用转换函数完成类类型到字符串指针的转换即“ char* ch = String ”的功能
// 仅含一个参数的构造函数可以作为参数类型到类类型的转换
// 使用explicit关键字限制只能进行强制类型转换
    explicit operator char*();
  1. 完整的String类的定义如下:

String.h

class String
{
private:
    char* str;
    int len;
public:
// 构造函数和析构函数
    String();
    String(char* s);
    ~String();

// 重载运算符
    String operator*(int num) const;
    friend String operator*(int num,const String & s);
    friend String operator+(const String & s1,const String & s2);
    friend std::ostream & operator<<(std::ostream & os,const String & s);
    friend std::istream & operator>>(std::istream & is,String & s);

// 强制类型转换函数
    explicit operator char*();
};
  1. 完整的实现为:

String.cpp

#include <iostream>
#include "String.h"
using namespace std;

String::String()
{
// 默认构造函数
    str = new char[1];  // 保证析构函数delete的一致性
    str[0] = '\0';
    len = 0;
}

String::String(const char* s)
{
// 使用字符串指针构造
    len = strlen(s);
    str = new char[len+1];
    strcpy(str, s);
}

String::~String()
{
// 析构函数释放内存
    len = 0;
    delete [] str;
}

String::String(const String & s)
{
// 复制构造函数
    len = s.len;
    delete [] str;
    str = new char[len+1];
    strcpy(str,s.str);
}

String String::operator*(int num) const
{
// 字符串乘法(成员函数)
    String result;
    result.len=len*3;       
    delete [] result.str;   // 释放原有内存
    result.str=new char[result.len+1];
    result.str[0]='\0';
    for(int i=0;i<num;i++)
        result.str=strcat(result.str,str);
    return result;
}

String & String::operator=(const String & s)
{
// 赋值重载函数需要注意:
// 1. 释放以前的内存
// 2. 防止赋值给自身
// 3. 返回引用值
    if(this == &s)
        return *this;
    len=s.len;
    delete [] str;
    str=new char[len+1];
    strcpy(str,s.str);
}

char & String::operator[](int num)
{
// 中括号重载,因为结果可为可修改的左值,所以返回值为非const引用
    return str[num];
}

const char & String::operator[](int num) const
{
// 中括号重载,适用于常对象的数据访问
    return str[num];
}

String operator*(int num,const String & s)
{
// 字符串乘法(友元函数)
    return s*num;
}

String operator+(const String & s1,const String & s2)
{
// 字符串加法
    String sum;
    sum.len = s1.len + s2.len;
    delete [] sum.str;
    sum.str = new char[sum.len+1];
    strcpy(sum.str,s1.str);
    strcat(sum.str,s2.str);
}

ostream & operator<<(ostream & os,const String & s)
{
// 重定义<<
    os<<s.str;
    return os;
}

istream & operator>>(istream & is,String & s)
{
// 重定义>>
    is>>s.str;
    s.len=strlen(s.str);
}

String::operator char*()
{
// 转换函数(String类->字符串指针)
    char* s=new char[len+1];
    strcpy(s,str);
    return s;
}
  1. 上述代码中涉及返回对象的选择,const、引用和普通对象,需要从实际含义去理解

原文地址:https://www.cnblogs.com/wheel-maker/p/15138899.html