プレイC++演算子リロード


演算子リロード構文:戻り値タイプoperator演算子(パラメータリスト){コードロジック...}
C++の演算子のリロードは関数によって実現され、リロードされた演算子をクラスのメンバー関数と見なし、通常の関数のように呼び出すことができます.Stringクラスの+演算子を再ロードする場合は、次のように呼び出すことができます.
class {
   // .....
   String operator+(const String &str)
   { .... }
}

String str1 = "hello ";
String str2 = "cplusplus";
String str3 = str1.operator+(str2);
        
上記のコードから、operator+はStringクラスの関数のように、通常の関数のように呼び出し、加算する文字列オブジェクトを実パラメータとして関数に渡せばよいことがわかります.したがって、これから関数リロードのステップが得られる:(上記+リロードを例に)
1、書き出し演算子の関数プロトタイプ
str1.operator+(str2); 
このことから、+は2つのオペランド、str 1とstr 2(すなわち2つの文字列オブジェクト)を必要とし、戻り値タイプはStringオブジェクト(加算演算後の結果)であることが分かる.クラスとしてのメンバー関数のリロードであるため、str 1は+演算時にthisポインタとして関数に渡され、関数は1つのパラメータ、すなわち加算された文字列オブジェクトstr 2のみを必要とする.
2、関数宣言の書き出し
関数プロトタイプから関数宣言が得られます:String operator+(const String&str);
3、実現関数の詳細
String String::operator+(const String &str)
{
    if (str.buff == nullptr)
    {
        return *this;
    }
    
    size_t totallen = str.len + this->len + 1;
    char *buff = new char[totallen];
    
    strcpy(buff, this->buff);
    strcat(buff, str.buff);
    
    String temp(buff);
    return temp;
}

次の例では、文字列操作の一般的なオペレータを再ロードします.
//
//  String.h
//  C++     
//
//  Created by    on 14-5-8.
//  Copyright (c) 2014  yangxin. All rights reserved.
//

#ifndef __C______String__
#define __C______String__

#include <iostream>

using namespace std;

class String
{
private:
    char *buff;
    size_t len;
    
public:
    String();
    
    //            
    String(const char *buff);
    
    //     
    String(const String &str);
    
    //   
    ~String();
    
    //        
    void setString(const char *buff);
    
    //         
    size_t length() const;
    
    //        
    char * getStr() const;
    
    //            
    bool operator==(String &str);
    
    //             
    bool operator!=(String &str);
    
    //           
    bool operator>(String &str);
    
    //           
    bool operator<(String &str);
    
    //                
    char& operator[](int index);
    
    //       
    String& operator=(const String &str);
    
    //        
    String operator+(const String &str);
    
    //      
    String& operator+=(const String &str);
    
    //           
    friend istream& operator>>(istream &input, String &str);
    
    //           
    friend ostream& operator<<(ostream &output, const String &str);
    
};

#endif /* defined(__C______String__) */

//
//  String.cpp
//  C++     
//
//  Created by    on 14-5-8.
//  Copyright (c) 2014  yangxin. All rights reserved.
//

#include "String.h"
#include <string>
#include <cassert>
#include <cmath>

String::String()
{
    this->buff = nullptr;
    this->len = 0;
}

//            
String::String(const char *buff):buff(nullptr), len(0)
{
    setString(buff);
}

//     
String::String(const String &str)
{
    setString(str.buff);
}

//   
String::~String()
{
    //     
    if (this->buff != nullptr)
    {
        delete[] buff;
        buff = nullptr;
        len = 0;
    }
}

void String::setString(const char *buff)
{
    if (buff == nullptr)
    {
        return;
    }
    
    if (this->buff != nullptr) {
        delete[] this->buff;
        this->buff = nullptr;
        this->len = 0;
    }
    
    size_t len = strlen(buff);
    this->buff = new char[len + 1];
    this->len = len;
    strcpy(this->buff, buff);
}

//         
size_t String::length() const
{
    return this->len;
}

//        
char * String::getStr() const
{
    return this->buff;
}

//                
char& String::operator[](int index)
{
    assert(index < this->len);
    
    return this->buff[index];
}

//            
bool String::operator==(String &str)
{
    if (this->len != str.len)
    {
        return false;
    }
    
    for (int i = 0; i < this->len; ++i)
    {
        if (this->buff[i] != str[i])
        {
            return false;
        }
    }
    
    return true;
}

//             
bool String::operator!=(String &str)
{
    return !(*this == str);
}

//           
bool String::operator>(String &str)
{
    char *pstr = this->buff;
    char *pstr2 = str.buff;
    while (*pstr != '\0' && *pstr2 != '\0')
    {
        if (*pstr > *pstr2) {
            return true;
        }
        pstr++;
        pstr2++;
    }
    return false;
}

//           
bool String::operator<(String &str)
{
    return !(*this > str);
}

//       
String& String::operator=(const String &str)
{
    setString(str.buff);
    
    return *this;
}

//        
String String::operator+(const String &str)
{
    if (str.buff == nullptr)
    {
        return *this;
    }
    
    size_t totallen = str.len + this->len + 1;
    char *buff = new char[totallen];
    
    strcpy(buff, this->buff);
    strcat(buff, str.buff);
    
    String temp(buff);
    return temp;
}

//      
String& String::operator+=(const String &str)
{
    if (str.buff == nullptr)
    {
        return *this;
    }
    
    //          ,                 
    size_t len = this->len + str.length();
    char *temp = new char[len + 1];
    strcpy(temp, this->buff);
    strcat(temp, str.buff);
    
    //             
    setString(temp);
    
    return *this;
}

//           
istream& operator>>(istream &input, String &str)
{
    //           ,      
    int size = 1024 * 10;
    char *tempbuff = new char[size];
    memset(tempbuff, 0, size);
    
    //       
    input.getline(tempbuff, size);
    
    //              str          
    str.setString(tempbuff);
    
    //          
    delete[] tempbuff;
    tempbuff = nullptr;
    return input;
}

//           
ostream& operator<<(ostream &output, const String &str)
{
    output << str.getStr();
    return output;
}

//     
//
//  main.cpp
//  String(     )
//
//  Created by    on 14-5-8.
//  Copyright (c) 2014  yangxin. All rights reserved.
//

#include <iostream>
#include "String.h"
#include <cmath>

using namespace std;


int main(int argc, const char * argv[])
{
   
    //    
    String str1("helloz");
    String str2("helloz");
    
    //        
    cout << str1.getStr() << endl;
    
    //         
    cout << "  :" << str1.length() << endl;
    
    //              
    cout << " 1   :" << str1[0] << endl;
    
    //            ,    1,    0
    bool isequal = str1 == str2;
    cout << isequal << endl;
    
    //           ,str1  str2  1,    0
    cout << (str1 > str2) << endl;
    
    //         2    C
    String s = "Hello";
    s[1] = 'C';
    cout << s << endl;
    
    //                    
    String str3 = str2;
    cout << str3.getStr() << endl;
    String str4;
    str4 = str3;
    cout << str4.getStr() << endl;
    
    //          
    String str5 = str1 + str2;
    cout << &str5 << endl;
    cout << str5.getStr() << endl;
    
    //        
    String str6;
    String str7 = str6 = str5;
    cout << str6.getStr() << " | " << str7.getStr() << endl;
    
    //        
    String str8 = "i love c++ ";
    str8 += "i love c ";
    cout << str8.getStr() << endl;
    
    //          
    String str9;
    cout << "Please a string:";
    cin >> str9;
    
    //           
    cout << str9 << endl;
   
    return 0;
}

演算子のリロードに関する注意事項:
  • 友元関数リロード演算子の場合、すべてのオペランド
  • を渡す必要があります.
  • メンバー関数がリロードされると、オペランド自体がthisポインタとしてパラメータ伝達関数として使用され、マルチオペレータであれば、操作する数伝達関数として
  • を使用できます.
  • =号リロード時、オブジェクトに新しく割り当てられたメモリのメンバーがいる場合はdelete、new、接続などの操作をサポートするには、オブジェクト自体の参照
  • を返す必要があります.
  • 関数の戻り値が左の場合、戻り値は参照
  • でなければならない.
  • は、C++の事前定義されたオペレータセットのオペレータのみをリロードできます(+-などのオペレータを自分で勝手に書くことはできません)
  • .
  • リロードオペレータは、オペレータの優先度を変更することはできません.例えば、徐を先に乗算し、
  • を減算します.
  • リロードオペレータはオペランドの個数を変えることができない
  • .
    次の演算子は再ロードできません.
  •  . :メンバー選択演算子
  • :::役割ドメイン演算子
  • *:ポインタ演算子
  • #:前処理フラグ
  • ?: :三目演算子、確定性なし、リロード意味なし