gpt4 book ai didi

c++ - 重载 '<<' 运算符的问题

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:51:40 25 4
gpt4 key购买 nike

创建自定义 String 类时,我无法为输出重载“<<”运算符。我尝试了几种不同的编写方式(在下面的代码中注释掉,以供引用,因为它们不起作用),但出现了各种错误。对于初学者,我从下面的代码中得到的错误是:

错误 1:错误 C2804:二进制“运算符 <<”第 53 行的参数过多

错误2:error C2333: 'String::operator <<' : 函数声明错误;跳过函数体第 53 行

错误 3:错误 C2679:二进制“<<”:未找到接受类型为“String”的右手操作数(或没有可接受的转换)的运算符第 180 行(有很多)

由于文件超过 300 行,我怀疑你们需要通读一遍,我会 --snip-- 一些,但如果你想要 300 行,我一定会编辑它.

此外,我知道 header 中的“使用命名空间标准”是不好的做法。抱歉,这是我正在使用的旧文件,我保证不会将它包含在未来的头文件中。

也就是说,这是代码(非常感谢您的帮助):

正如我之前所说,非常感谢那些在下方阅读和回复的人。我花了将近两个小时试图找到一个可行的解决方案,而我搜索的帖子要么太复杂以至于我无法理解,要么不适用于我的情况。通过查看 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();
 * };
 */

最佳答案

您需要插入运算符才能成为自由函数:

你的类主体中:

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

在您的类(class)主体之外:

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

这假设 GetText() 是一个可行的成员函数,在您当前的代码片段中找不到它。我假设你在某个地方有一个。如果是public,则无需在类体中声明友元关系,只需使用自由函数插入运算符即可。

最后,这假设运算符是在头文件中实现的(因此是内联的)。如果将实现移至 .cpp 文件,请务必在 header 中将其声明为全局原型(prototype)删除 .cpp 实现中的 inline 序言。

旁注:打破将 using namespace std; 放在头文件中的习惯现在。这是一种不好的做法,可能会对源文件(包括您的 header )产生不需要的命名空间暴露的副作用。

关于c++ - 重载 '<<' 运算符的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15352656/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com