C++函数参数:字符指针和字符串

4
void callme(string a)
{
  cout<<"STRING CALLED"<<endl;
}

void callme(char * a)
{
  cout<<"char pointer called"<<endl;
}

int main()
{
   callme("ASDADS");
   return 0;
}

为什么会调用char*?为什么当我注释掉带有char*参数的函数时,其他函数会被调用?

1
编辑器中有帮助按钮,可以阅读。对于代码,请选择您的代码块,然后单击“ {}”按钮或按Ctrl + K。 - Mat
4个回答

4
那是因为"ASDADS"可以转换成char *。编译器因此会生成代码,匹配到第一个函数的参数。
如果你删除char *原型,编译器将寻找接受从char *到参数类型的隐式转换的函数。
以以下代码为例:
class A
{
public:
    A() {}
    A(int x) {}
};

//void foo(int x) {}
void foo(A x) {}

int main(int argc, char* argv[])
{
    int x = 3;
    foo(x);
}

如果您注释掉foo(int x),则将调用其他函数。

然而,如果您将构造函数声明为explicit,则会出现错误:

class A
{
public:
    A() {}
    explicit A(int x) {}
};

3
字符串字面值(如"abc")的类型是“const char的数组”。但是,作为一项特殊规则,C++允许将其转换为char*(已经被弃用)。这种转换优先于由构造函数string::string(const char*)提供的用户定义转换。因此,在重载决议中,char*的重载版本胜出(相对于string有零个用户定义转换,而仅有一个用户定义转换)。
(实际上我无法找到关于此的标准参考;相反,C.1.1明确表示,在C++中char * p = "abc"是“无效的”。欢迎任何进一步的输入。编辑:看起来这是从C++03到C++11的变化,在C++11中这是绝对不合法的。)

我认为这是编译器扩展。但我从来没有真正理解过,为什么你可以有 char* = "foo";,但是当你尝试更改它时会遇到未定义行为。为什么不强制将其声明为 const char* 呢? - Luchian Grigore
@LuchianGrigore:即使在GCC上使用“-pedantic”,它也会说“已弃用的转换”,因此它似乎不是扩展... - Kerrek SB
我在谈论MSVS2008。我甚至没有收到警告。 - Luchian Grigore

0

当你有两个函数时,有两种选择可供选择,而(char *)更适合于你的参数“ASDADS”。如果你删除(char *)函数,那么就只有一个函数需要一个字符串。因此编译器使用一个带有char*参数的字符串构造函数来创建一个字符串。

http://www.cplusplus.com/reference/string/string/string/


0

默认情况下,“ASDADS”由char指针引用。因此使用callme()的第二个版本。如果将其注释掉,编译器将尝试将其与字符串匹配,因此使用callme()的第一个版本。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接