2

カスタム文字列クラスを作成していますが、出力用の「<<」演算子をオーバーロードするのに問題があります。私はそれを書くいくつかの異なる方法を試しました(参考のために、そしてそれらが機能しなかったので、以下のコードでコメントアウトされています)、さまざまなエラーが発生します。まず、以下のコードから得られるエラーは次のとおりです。

エラー 1: エラー C2804: バイナリ 'operator <<' には 53 行目のパラメーターが多すぎます

エラー 2: エラー C2333: 'String::operator <<' : 関数宣言のエラー。関数の本文行をスキップする 53

エラー 3: エラー C2679: バイナリ '<<' : タイプ 'String' の右側のオペランドを取る演算子が見つかりません (または、受け入れ可能な変換がありません) 180 行目 (これらはたくさんあります)

このファイルは 300 行を超えているので、すべてを読む必要があるとは思えないので、一部を省略しますが、300 行が必要な場合は必ず編集します。

また、ヘッダーで「名前空間 std を使用する」ことは悪い習慣であることも知っています。申し訳ありませんが、これは私が使用している古いファイルであり、将来のヘッダー ファイルには含めないことを約束します。

とはいえ、これがコードです(そして、助けてくれてありがとう):

前に言ったように、以下を読んで返信してくれた人たちに感謝します。これに対する実行可能な解決策を見つけるのに 2 時間近く費やしましたが、検索した投稿は複雑すぎて理解できないか、私の場合には当てはまりませんでした。cplusplus の Web サイトを見ると、<< 演算子関数はパラメーターを 1 つしか取りませんが、その機能に問題があることがわかりました。皆さんがうまくいくと思うものを投稿してくれたら、私は試してみて返信します。

皆さんありがとう!重要な情報が不足している場合はお知らせください。

#pragma once

#include <iostream>
#include <sstream>
using namespace std;

#define NOT_FOUND -1

//ostream& operator << (ostream& out, const String& myString);

// C++ String class that encapsulates an ASCII C-string
class String
{
public:
    // Default constructor
    String()
    {
        Text = NULL;
    }
    
    // MUST HAVE: Copy-constructor that performs deep copy
    String(const String& source)
    {
        Text = NULL;
        // Call the assignment operator to perform deep copy
        *this = source;
    }
    
    // Init-constructor to initialize this String with a C-string
    String(const char* text)
    {
        Text = NULL;
        // Call the assignment operator to perform deep copy
        *this = text;
    }
    
    // Init constructor, allocates this String to hold the size characters
    String(int size)
    {
        Text = new char[size];
    }
    
    // Destructor
    ~String()
    {
        delete[] Text;
    }
    
    // This is what I would love to have work.
    ostream& operator << (ostream& out, const String& myString)
    {
        return out << myString.GetText();
    }
    // Returns a new string that corresponds to a substring of this String
// beginning at startPosition and length chars long;
// if length = 0 (not specified) then the substring spans from
// startPosition until the end of this String
// throws an exception when startPosition is out of bounds
String Substring(int startPosition, int length) const
{
    char * str = this->GetText();
    String returnString;
    int strLength = length;
    int x = 0;

    if(length == 0)
        strLength = GetLength(str)-startPosition;

    char* substring = new char[strLength];

    // Makes sure the starting position is within the bounds of the String 'this'
    try
    {
        CheckBounds(startPosition, str);
    }
    catch(char * error)
    {
        cout << error << endl << endl;
    }

    // In case the substring length is too long, it cuts short once it reaches the end of the original string. Yu-San, this is #2 on the three options you said I could implement, FYI.
    while(x < strLength && str[x+startPosition]!='\0')
    {
        substring[x] = str[x + startPosition];
        x++;
    }
    substring[x]='\0';
    //for(int x = 0; x<strLength; x++)
    //{
    //returnString = str + startPosition;
    returnString = substring;
    //}

    return returnString;    
}
    // Assignment operator to perform deep copy
    String& operator = (const char* text)
    {
        // Ddispose of old Text
        delete[] Text;
        
        // +1 accounts for NULL-terminator
        int trueLength = GetLength(text) + 1;
        
        // Dynamically allocate characters on heap
        Text = new char[trueLength];
        
        // Copy all characters from source to Text; +1 accounts for NULL-terminator
        for ( int i = 0; i < trueLength; i++ )
            Text[i] = text[i];
        
        return *this;
    }
    
    // Returns the count of characters in a C-string text; NULL-terminator is not counted
    // static means that the member function neither reads nor
    // writes any of the class' data members
    // String::GetLength("blah");
    static int GetLength(const char* text)
    {
        int x = 0;
        while(text[x] != '\0')
            x++;
        
        return x;
    }
    
    // Returns a reference to a single character from this String
    char& operator [] (int index) const
    {
        int length = GetLength();
        
        // Check for valid index
        if ( (index < 0) || (index > length) )
        {
            stringstream error;
            error << "operator[] - index " << index << " is out of bounds (0.." << (length - 1) << ")";
            throw String(error.str().c_str());
        }
        
        return Text[index];
    }
// Returns the count of characters in the String; NULL-terminator is not counted
int GetLength() const
{
    return GetLength(Text);
}



char* GetText() const
{
    return Text;
}

// Finds first index of a symbol not found in "text" in string *this
int FindFirstNotOf(char * text)
{
    String objectString(*this);
    int x = 0; // loop counter
    int firstIndex = 0; // index to return

    while(text[x]!='\0')
    {
        // runs each character in 'text' against each character in the object.
        for(int y = 0; y<objectString.GetLength(); y++)
        {
            if(objectString[x] == text[x])
                objectString[x] = '\0';
        }

        x++;
    }

    while(objectString[firstIndex]=='\0' && (firstIndex<objectString.GetLength()))
    {
        firstIndex++; //keeps running until it Finds a character that wasn't changed to \0
    }

    if(firstIndex == objectString.GetLength())
        firstIndex = -1; // means it wasn't found.

    return firstIndex;
}

int FindFirstOf(char iWantThis)
{
    String objectString(*this);
    int firstIndex = 0; // index to return

    while(objectString[firstIndex]!=iWantThis && (firstIndex<objectString.GetLength()))
    {
        firstIndex++; //keeps running until it Finds a character that wasn't changed to \0
    }

    if(firstIndex == objectString.GetLength())
        firstIndex = -1; // means it wasn't found.

    return firstIndex;
}

int FindLastOf(char iWantThis)
{
    String objectString(*this);
    int index = 0;
    int lastIndex = -1;

    while(objectString[index]!='\0')
    {
        if(objectString[index] == iWantThis)
            lastIndex = index;
    }

    return lastIndex;
}

// finds a desired char in String object, with default start index of 0
int Find (char iWantThis, int startIndex = 0)
{
    int index = -1;
    int ctr = startIndex;

    String objectString(*this);

    while(objectString[ctr]!='\0' && index == -1) // runs until it reaches end, or the return index is changed
    {
        if(objectString[ctr] == iWantThis)
            index = ctr;
        else
            ctr++;
    }

    return index;
}

private:

// Throws an String-type exception when index is out of bounds
void CheckBounds(int index, const char* source) const
{
    int size = GetLength(source);

    if(index < 0 && index >=size)
        throw "Selected Starting Index is Out of Bounds.";  
}

// The encapsulated C-string
char* Text;
};


// Stream output operator to print String to output stream
/* ostream& operator << (ostream& out, const String& myString)
 * {
 *  return out << myString.GetText();
 * };
 */
4

1 に答える 1

2

自由関数になるには、挿入演算子が必要です。

クラス本体の内部:

class String
{
   friend std::stream& operator <<(std::ostream&, const String&);
   ...
};

クラス本体の外:

inline std::ostream& operator << (std::ostream& os, const String& myString)
{
    os << myString.GetText();
    return os;
}

GetText()これは、実行可能なメンバー関数であると想定していますが、現在のコードスニペットではどこにも見つかりません。どこかにあると思います。その場合はpublic、クラス本体でフレンド関係を宣言する必要はなく、自由関数挿入演算子を使用するだけで済みます。

最後に、これは、演算子がヘッダーファイル(したがってインライン)に実装されていることを前提としています。実装を.cppファイルに移動する場合は、ヘッダーでグローバルプロトタイプとして宣言し、.cpp実装のプリアンブル削除してください。inline

補足:今すぐusing namespace std;ヘッダーファイルを挿入する習慣を破ってください。これは悪い習慣であり、名前空間の公開が予期されていないヘッダーを含むソースファイルに望ましくない副作用をもたらす可能性があります。

于 2013-03-12T03:25:40.500 に答える