2013-03-12 129 views
2

創建一個自定義字符串類,並且我無法將超出的'< <'運算符輸出。我嘗試了幾種不同的編寫方式(在下面的代碼中註釋掉,以供參考,因爲它們不起作用),並且得到各種錯誤。對於初學者來說,錯誤我從下面的代碼得到的是:超載「<<」運算符的問題

錯誤1:錯誤C2804:二進制「操作符< <」有太多的參數出線53

錯誤2:錯誤C2333:「字符串::運算符< <':函數聲明中的錯誤;跳過功能體線53

錯誤3:錯誤C2679:二進制'< <':找不到操作符找到類型'String'的右側操作數(或沒有可接受的轉換)第180行(有一堆這些)

由於該文件超過300行,我懷疑你們需要通讀這一切,我會--snip--一些,但如果你想300線我會一定要編輯這個。

此外,我知道在標頭中使用名稱空間標準是不好的做法。對不起,這是我正在使用的一箇舊文件,我保證我將不會將它包含在將來的頭文件中。

這就是說,這裏的代碼(非常感謝您的幫助):

正如我之前所說,由於一噸的閱讀及以下響應。我花了近兩個小時試圖找到一個可行的解決方案,我搜索的帖子要麼太複雜,我不明白,或不適用於我的情況。從查看cplusplus網站,我看到運算符函數只需要一個參數,但是遇到了問題。如果你們發佈了你認爲可行的方式,我會盡力並回復。

謝謝大家!如果我遺漏了任何重要信息,請告知我們。

#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

二元'運算符<<'應該是一個自由函數而不是成員函數。成員'operator <<'只能有一個參數,這個參數是表達式的右邊。 在代碼結尾處,您似乎將運算符作爲免費函數作爲註釋。爲什麼這種嘗試失敗了? – Pablo 2013-03-12 03:23:56

+0

@Pablo感謝您的快速回復。有幾個try/catch語句用'<<'運算符來檢查各種函數中的邊界,以及類中的其他錯誤檢查代碼。它顯示與「錯誤3」相同的錯誤從頁面頂部。另外,感謝您對問題的格式的幫助:)當運算符重載是底部的一個自由函數時,類不知道'<<'的含義。如果我在頂部聲明它,我會得到一個錯誤:「錯誤C4430:缺少類型說明符 - int假定。注意:C++不支持缺省-int」 – Reciever80 2013-03-12 03:26:30

回答

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;在你的頭文件現在的習慣。這是一種不好的做法,並且可能會對源文件產生不必要的副作用,包括您的頭文件,這些文件名不在名稱空間中。

+0

當運算符重載是底部的一個自由函數時,類不會'不知道'''是什麼意思。如果我在頂部聲明它,我會得到一個錯誤:「錯誤C4430:缺少類型說明符 - 假定爲int。注意:C++不支持缺省-int。」事後看來,只有在網上發佈您的問題後,我才意識到c字符串的工作方式也是如此,但爲了將來的參考,那裏將有哪些解決方案? – Reciever80 2013-03-12 03:43:42

+0

@ Reciever80爲什麼「類」本身首先使用該運算符?除了'friend' decl外,應該沒有在類中聲明*的插入操作符,並且只有在需要的時候。你究竟在爲什麼在類中使用自由函數插入運算符*?你可以發佈在類中使用*的代碼嗎?記住,正如發佈的那樣,我們沒有你的代碼(缺少GetText(),並且所有成員變量都是最好的證據),所以我們在這裏用盲目飛行。 – WhozCraig 2013-03-12 03:47:20

+0

有幾個try/catch語句用'<<'操作符來檢查各種函數中的邊界以及類中的其他錯誤檢查代碼。它會打印一個字符串,說「超出範圍」。發佈後我意識到(這是我在網上發佈問題後纔得到的諷刺後見證),我可以用c字符串代替。我會爲OP增加一些功能,只是爲了避免讀取太多的信息。儘管在課程本身內部使用「字符串」,這實際上仍然完美。你是男人! – Reciever80 2013-03-12 04:56:11