【问题标题】:Error with setter method: argument of type "const char *" is incompatible with parameter of type "char *"setter 方法出错:“const char *”类型的参数与“char *”类型的参数不兼容
【发布时间】:2021-06-06 15:36:48
【问题描述】:

我试图在某个课程中为 name 创建一个设置器,但我遇到了这个问题。

void Cats::setName(char* s) {
    if (this->name != NULL) {
        delete[] name;
        name = new char[strlen(s + 1)];
        strcpy_s(s, strlen(name) + 1, name);
    }
}

这是二传手,我不能为我的任何Cat 写任何名字。

Cats::Cats() {
    setName("NoName"); <----- problem here and in other constructors also.
    setWeight(0.6);
    setAge(0);
}

“const char *”类型的参数与“char *”类型的参数不兼容

我怎样才能做到这一点?我错过了什么?一个解释会很棒。

【问题讨论】:

  • 注意strlen(s + 1)必须是strlen(s) + 1

标签: c++


【解决方案1】:

"NoName"const char*const 表示没有人可以修改其中的字符。您的函数采用char*,它是一个可变字符数组。您不能将常量数据传递给其签名需要可变数据的函数。如果你真的不打算修改数组,那就拿一个const char*

void Cats::setName(const char* s)

或者,更好的是,正如 Bathesheba 指出的那样,使用 std::string,它将为您管理内存。

void Cats::setName(std::string s)

在现代 C++ 中,直接使用 newdelete 通常是代码异味,应该避免。我们有std::string 用于字符串,std::arraystd::vector 用于数组,std::unique_ptrstd::shared_ptr 用于拥有的堆内存。让您的类型自己说话,编译器会为您处理内存管理。

【讨论】:

  • 太好了!所以我知道我应该避免在设置器中直接使用newdelete。我将只使用std::string,函数将只是this-&gt;name = s
  • 正确。一般来说,您应该避免使用newdelete。它们是低级的高级技术,需要非常小心和注意才能最大限度地减少错误。
  • 你有机会了解 constness。保留你的 new 和 delete,使函数采用 const char 指针。字符串建议是一个很好的建议,但它剥夺了你了解 const 正确性的机会
  • 是的,我试图弄清楚。反正还是没有运气。也许别的东西不好。会继续努力,谢谢:)
  • ""NoName" is a const char*" - 从技术上讲,它是一个const char [7],在某些情况下衰减const char*上下文,例如在函数参数中。
【解决方案2】:

对于初学者来说,setter 中的这个语句

name = new char[strlen(s + 1)];

不正确。它应该看起来像

name = new char[strlen(s ) + 1];

尽管如此,该函数至少应按以下方式定义

void Cats::setName( const char *s ) {
    if (this->name != nullptr) delete[] name;

    size_t n = strlen( s ) + 1;
    name = new char[n];
    strcpy_s(s, n, name);
}

您正在调用传递给它的字符串文字的函数

Cats::Cats() {
setName("NoName"); <----- problem here and in other constructors also.
setWeight(0.6);
setAge(0);
}

在 C++ 中,与 C 字符串文字相对的是常量字符数组类型。因此,setter 的参数应声明为

const char *s

并且构造函数至少应该看起来像

Cats::Cats() : name( nullptr ) {
    setName("NoName");
    setWeight(0.6);
    setAge(0);
}

前提是在类定义中数据成员名没有用 nullptr 显式初始化。

【讨论】:

  • if (this-&gt;name != nullptr) delete[] name;if 条件是多余的。
  • @prapin 也可以说在这种情况下调用 delete 是多余的。
猜你喜欢
  • 1970-01-01
  • 2019-12-16
  • 2016-05-19
  • 1970-01-01
  • 2020-01-20
  • 1970-01-01
  • 2014-07-03
  • 2021-08-06
  • 2020-11-19
相关资源
最近更新 更多