我有一个相当简单的类,如下所示:
class Person {
public:
Person(string name): _name(name) {};
void greet(const Person& person) const {
cout << "Hello, " << person._name << "!" << endl;
};
private:
string _name;
};
请注意,greet
方法采用Person
类型的参数。当我传递一个Person
对象时,它按预期工作。现在让我们以这种方式将string
作为参数传递给它:
Person maher("maher");
maher.greet("sam");
尝试在QT中运行该代码时(在运行ubuntu的计算机上),它会生成以下错误:
no matching function for call to ‘Person::greet(const char [4])’
我能够通过以这种方式强制转换字符串来解决此错误:maher.greet(string("sam"));
我的问题如下:为什么c ++ '看''我不能将字符串传递给greet
方法?是否与greet
方法接受Person
对象这一事实有关?
答案 0 :(得分:6)
maher
是const char[6]
,而sam
是const char[4]
,并且都隐式地衰减到const char *
,但它们实际上都不是std::string
explicit
1}}。
在函数调用中,如果目标类型的非const char[6]
构造函数接受传递给函数的实际值的类型,则C ++标准允许执行隐式转换。
当您调用构造函数时会发生这种情况:您传递const char *
,它会自动衰减为std::string
;目标类型为const char *
,其构造函数接受Person
;调用此类构造函数,std::string
构造函数正确接收其Person
参数。
在第二种情况下,没有发生这种情况:const char *
没有接受std::string
的构造函数,只有接受Person
的构造函数。要达到所需的const char *
类型,编译器必须先将std::string
转换为Person
,然后调用greet
构造函数。这种双重转换是不允许的,主要是因为重载分辨率会变得完全混乱(已经存在),并且存在许多模糊的情况。
如果你想允许用C风格的字符串调用Person
,你应该:
为const char *
创建一个接受C样式字符串(const char *
)的构造函数,以便可以直接从greet
构造,而不经过禁止额外转换
为std::string
创建另一个重载以接受maher.greet(std::string("sam"));
。
另一方面,IMO更清洁的替代方案就是保持原样;调用者只需编写
{{1}}
答案 1 :(得分:4)
您没有传递std::string
,而是传递类型为const char*
的C风格字符串。也为此添加构造函数:
Person(string name): _name(name) {};
Person(const char *name): _name(name) {};
请注意,虽然const char*
会自动转换为std::string
,但在这种情况下,这意味着有2次转化(const char *
&gt; std::string
&gt; Person
) ,这是不允许的。
答案 2 :(得分:3)
maher.greet("sam");
这需要两次转换:
const char[4]
到std::string
,以便Person(string)
可以被调用。std::string
到Person
,以便greet(const Person&)
可以被调用。但不允许进行链转换。
因此,您要么提供构造函数Person(const char*)
,要么传递std::string
以避免首次转换(如上所列):
Person(const char*)
,则const char[4]
将直接转换为Person
,然后将其传递给greet()
。std::string
传递给greet(),那么std::string
将使用代码中的现有构造函数转换为Person
,然后person对象将传递给{{ 1}}最终。在这两种情况下,只有一次转换。
或者,只需写下:
greet()
答案 3 :(得分:0)
它绝对“看到”你传递了一个字符串,这就是问题所在。您没有接受字符串作为输入的方法。
答案 4 :(得分:0)
greet方法是否接受Person对象,这与事实有什么关系?
是的,
您可以将字符串传递给greet()
方法,因为Person
类中有一个构造函数,它通过传递给它的字符串构造一个Person
对象。
传递char[4]
要求char[4]
首先是字符串对象,然后应用上述转换。这种转换链接是不允许的,因此。
答案 5 :(得分:-1)
您可以覆盖接受字符串的方法。
void greet(const string name) const {
cout << "Hello, " << name << "!" << endl;
};