我是c++的新手,正在编写一个简单的程序来测试如何处理字符串。我定义了一个单独的函数,它返回一个字符串,并希望在main方法中调用它。相同的代码在main方法中工作,但我需要将其定义为一个单独的函数。
我的代码如下:
7 #include <cstdlib>
8 #include <iostream>
9 #include <string>
10
11 using namespace std;
12
13 // function declaration
14 string hi();
15
16 int main(int argc, char** argv) {
17 // call method
18 string hi;
19 hi = hi();
20 cout << hi << endl;
21 }
22
23 string hi() {
24 //simple string function
25 return "Hello World";
26 }
下面是当我尝试用g++编译时返回到控制台的错误:
test.cpp: In function ‘int main(int, char**)’:
test.cpp:19:13: error: no match for call to ‘(std::__cxx11::string {aka std::__cxx11::basic_string<char>}) ()’
hi = hi();
^
用变量名遮蔽函数声明。你可以做两件事中的一件:
- 重命名函数或变量。(例子)
- 限定调用中的名称,这将涉及调用函数的名称空间(即。全局命名空间),如下所示:
::hi()
。(例子)
代码中的问题
您将变量名和函数名命名为hi
,因此编译器会混淆您指的是哪个。
解决方案1
正如@Cheersandhth所说,这样做:
hi = ::hi();
获取全局命名空间中的全局hi
,即函数。
生活例子/kbd>
解决方案2
否则,如果您想更改变量名,您可以将函数名或变量更改为不同的值,然后就可以工作了。下面是一个例子:
int main(int argc, char** argv)
{
string l_hi;
l_hi = hi();
cout << l_hi;
}
或替代:
int main(int argc, char** argv)
{
string hi;
hi = hello();
cout << hi;
}
string hello()
{
return "Hello, World!";
}
这两种解决方案都可以,您想使用哪一种解决方案取决于您的偏好。另外,使用这个答案作为不要使用名称遮蔽的建议,这可能会导致编译器选择两个名称中的一个(如果它们适合正确的上下文),或者可能会抛出错误。
3
解决方案等等,还有第三种解决方法吗?
是的,但是解决方案三更像是一种变通方法,尽管我更喜欢它。只要去掉变量本身,然后像这样添加cout
:
cout << hi(); //So simple!
我认为错误消息相当清楚:main中的hi隐藏了全局的hi函数。在某个地方使用另一个名称或作用域:hi = hi() => hi =::hi();
Try
string hi();
int main(int argc, char** argv) {
string _hi;
_hi = hi();
cout << hi << endl;
}
string hi() {
return "Hello World";
}
编译器抛出错误的原因是因为它将hi
后面的括号解析为函数调用。但是c++中的string
类没有函数调用操作符成员函数。所以,当它看到hi()
时,它会感到困惑,因为它认为你在谈论你刚刚在前一行声明的string hi
变量。因此,要将hi
变量与返回string
的hi()
函数区分开来,您可以执行以下一项或两项操作:
- 您可以将本地声明的
string
变量重命名为与全局函数不匹配的东西,反之亦然。 - 你可以用全局命名空间限定符作为函数调用的前缀,告诉编译器你正在使用全局
hi()
函数。(即。::hi()
)。
第一个例子:
#include <iostream>
#include <string>
using namespace std;
string hi();
int main(int argc, char** argv) {
string my_hi;
my_hi = hi();
cout << my_hi << endl;
return 0;
}
string hi() {
return "Hello, world!";
}
秒的例子:
#include <iostream>
#include <string>
using namespace std;
string hi();
int main(int argc, char** argv) {
string hi;
hi = ::hi();
cout << hi << endl;
return 0;
}
string hi() {
return "Hello, world!";
}
因为类可以重载函数调用操作符,所以有时看起来像在调用普通函数,但编译器可能正在调用函数调用操作符。良好的命名实践可以帮助最小化这些问题,但有时您可能需要具体一些,并包括全局名称空间限定符,以便向编译器澄清您的意思。如果string
类定义了函数调用操作符,则不会出现编译错误,但您将无法得到想要的答案)。