【问题标题】:C++ plus operator not working with const char and othersC++ plus 运算符不能与 const char 和其他运算符一起使用
【发布时间】:2023-03-12 23:24:01
【问题描述】:

你好,我做了一个像string 这样的变量存储,这是源代码

class str
{
private:

    const char * _mystring;

public:

    // Using this function to made new str
    str(const char * _str) { _mystring = _str; }

    // Get the content of this str
    const char * read() { return _mystring; }

    // Get the content in char *
    char * read_c() { return strdup(_mystring); }

    // Operator for equal action with extern const char
    str & operator = (const char * _str) { _mystring = _str; return *this; }

    // Operator for equal action with extern str storage
    str & operator = (str _str) { _mystring = _str.read(); return *this; }

    // Operator for add action
    str operator + (const char * _str) {
        return str(strcat(read_c(), _str));
    }

    // Operator for add action with new str
    str operator + (str & _str) {
        return str(strcat(read_c(), _str.read()));
    }
};

这是我的测试程序

int main() {

    str var1("Var1"); // No problem
    str var2("Var2"); // No problem

    str var3 = var1 + var2;  // No problem
    str var4 = var1 + "tempStr"; // I got runtime error !
    str var5 = "tempStr" + var2; // I got error before compile

    cout << var1.read() << endl;
    cout << var2.read() << endl;
    cout << var3.read() << endl;
    cout << var4.read() << endl;

    return 0;
}

问题是什么,我无法创建类似 var3 和 var4 之类的东西并且出现错误(当我想将 const char 与我的 str 合并时出现错误......我设置了 + 运算符,但是当我出现问题时想将 const char 与我的 str 合并(不是我的 str 与 const char ......在这个动作上,没有问题) 但是等一下,我在编译和打印 var7 后也出现错误(调试(关闭程序))!

【问题讨论】:

  • 您具体遇到了什么错误?是编译错误还是运行时错误?还要注意 strcat 不分配所以如果你的缓冲区不够大,它是未定义的行为
  • 运行时错误...
  • 是的,因为您要添加 2 个指针

标签: c++ string


【解决方案1】:

对于str var3 = "tempTxt0" + "tempTxt1" + "tempTxt2"; // Error

这不起作用,因为编译器会看到这些类型(省略变量名):str = const char* + const char* + const char *。将 char 指针添加在一起不是您想要的。但是,如果您只有其中一个类型为class str,它会起作用。例如。 str = str(const char*) + const char* + const char * 将调用 str::operator+,它返回一个 str 类型的新对象,其余的将遵循相同的方式。

对于str var4 = "tempTxt3" + var1; // Error

这不起作用,因为您将operator+ 声明为成员函数。编译器再次看到这些类型(省略变量名):str = const char* + str。没有 operator+ 声明 for const char* 作为第一个操作数str 作为第二个操作数。您有一个成员 operator+,但该运算符在 class str 上工作,因此您需要在左侧有一个 class str;如str + const char*。把它想象成一个函数调用,因为它正是一个 member 函数调用。与输入str = str.operator+("text") 相同。现在你看,str = "text".operator+(str) 不起作用,因为 它不存在

如果你声明了一个非成员函数str operator+(const char* first, const str&amp; second);,它会起作用。编译器将在参数的外部命名空间范围内查找与您想要的匹配的运算符,直至全局范围(这称为 ADL)。但是有一个更好的方法:

声明str operator+(const str&amp; lhs, const str&amp; rhs);。如果您以这种方式声明运算符class str 的命名空间范围,那么编译器将使用第二个参数的类型(class str)使用 ADL(on Wikipedia)并找到此运算符.然后,编译器可以看到class str 有一个非显式构造函数,它可以采用const char*str(const char * str)。然后它可以创建一个class str 的临时对象并使用您定义的operator+

因此,对于您的示例,由于您没有任何命名空间,因此您需要最简单的方法(注意我添加了一些 const 关键字):

class str
{
private:

    const char * _mystring;

public:

    // Using this function to made new str
    str(const char * _str) { _mystring = _str; }

    // Get the content of this str
    const char * read() const { return _mystring; }

    // Get the content in char *
    char * read_c() const { return strdup(_mystring); }

    // Operator for equal action with extern const char
    str & operator = (const char * _str) { _mystring = _str; return *this; }

    // Operator for equal action with extern str storage
    str & operator = (str _str) { _mystring = _str.read(); return *this; }
};

// Operator for add action with new str
str operator+ (const str& lhs, const str& rhs) {
    return str(strcat(lhs.read_c(), rhs.read()));
}

附: 你的例子有更多的问题。 read_c 复制 10 个字节的字符串(比如说),并在其末尾连接更多字节。这是一个溢出,因为您的重复缓冲区是 10 个字节。您必须正确分配和释放内存,但我猜这是另一个问题。例如

str operator+(const str& lhs, const str& rhs) {
  const std::size_t ls = lhs.size();
  const std::size_t rs = rhs.size();
  char* n = new char[ls + rs + 1];
  std::memcpy(n, lhs.read(), ls);
  std::memcpy(n + ls, rhs.read(), rs);
  n[ls + rs] = '\0';
  return str(n);
}

那你还有什么时候到delete的问题。

【讨论】:

  • 老兄,谢谢,但你能编辑我的代码吗?我理解你所说的,但在(命名空间范围)部分我需要查看实时代码
  • 老兄,当 memcpy 在参数上为 const 时,您不能使用 memcpy,但我仍然遇到类似 str var4 = "Var4" + "tempStr1"; 的问题
  • @user216085 n 在 memcpy 上不是 const。第二个参数可以是const。见en.cppreference.com/w/cpp/string/byte/memcpy
  • 不,我不谈论 (n) .... 我在谈论函数参数(const str 和 const str)
【解决方案2】:
str var3 = "tempTxt0" + "tempTxt1" + "tempTxt2"; // Error
str var4 = "tempTxt3" + var1; // Error

在这些行中,您尝试添加 2 个指向某个静态内存的指针(换句话说,您的操作符没有被调用)

在运算符的左侧加上需要成为你的类

拥有一个空的(仅适用于 \0)类的实例将修复您的错误(正如您可能已经注意到的那样):

str var4 = str("") + "tempTxt3" + var1; //now it is okay

另外,请注意strcat 不会为连接分配内存,您必须自己使用realloc 来完成

【讨论】:

    【解决方案3】:

    当您覆盖 + 等二元运算符时,左操作数必须是相关对象。你得到错误的原因是因为左操作数是一个字符串常量,这是使用默认的+

    您需要为这些运算符创建友元函数,第一个参数接受 const char *,第二个参数接受 strconst char *

    【讨论】:

    • and either str or a const char * for the second parameter. - 您不能为原始类型重载运算符,至少一个参数必须是类或枚举类型。
    【解决方案4】:

    str var4 = var1 + "tempStr"; // 我遇到了运行时错误!

    在这种情况下,调用运算符+重载:

    str operator + (const char * _str) {
        return str(strcat(read_c(), _str));
    }
    

    您在一个指针上调用strcat,该指针指向的缓冲区不够大,无法同时包含当前字符串和_str。最快的解决方案是使用std::string,否则你需要分配足够大的缓冲区并记住要注意它的生命周期(遵守三规则等)

    str var5 = "tempStr" + var2; // 编译前出错

    您需要以下签名的全局运算符重载:

    str operator + (const char * _str, const str& s);
    

    【讨论】:

      猜你喜欢
      • 2020-10-21
      • 1970-01-01
      • 2012-09-11
      • 1970-01-01
      • 1970-01-01
      • 2013-04-17
      • 2021-10-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多