我有一个相当简单的类,看起来像这样:
class Person {
public:
Person(string name): _name(name) {};
void greet(const Person& person) const {
cout << "Hello, " << person._name << "!" << endl;
};
private:
string _name;
};
Run Code Online (Sandbox Code Playgroud)
请注意,该greet
方法采用该Person
类型的参数.当我传递一个Person
对象时,它按预期工作.现在让我们string
以这种方式将它作为参数传递给它:
Person maher("maher");
maher.greet("sam");
Run Code Online (Sandbox Code Playgroud)
当试图在QT中运行该代码时(在运行ubuntu的机器上),它会生成以下错误:
no matching function for call to ‘Person::greet(const char [4])’
我能够通过以这种方式转换字符串来解决此错误: maher.greet(string("sam"));
我的问题如下:为什么c ++ '看不到'我将字符串传递给greet
方法?它与greet
方法接受Person
对象的事实有什么关系吗?
maher
是一个const char[6]
,sam
是一个const char[4]
,并且都是const char *
隐含的衰变,但它们实际上都不是std::string
.
在函数调用中,如果explicit
目标类型的非构造函数接受传递给函数的实际值的类型,则C++标准允许执行隐式转换.
当你调用构造函数时会发生这种情况:你传递一个const char[6]
,它会自动衰减到一个const char *
; 目标类型是std::string
,它有一个接受a的构造函数const char *
; 调用此类构造函数,Person
构造函数正确接收其std::string
参数.
在第二种情况下,没有发生这种情况:Person
没有接受a const char *
的构造函数,只有接受a的构造函数std::string
.要达到所需的Person
类型,编译器必须首先转换const char *
为std::string
,然后调用Person
构造函数.这种双重转换是不允许的,主要是因为重载分辨率会变得完全混乱(已经存在),并且存在许多模糊的情况.
如果你想允许greet
用C风格的字符串调用,你应该:
创建一个构造函数Person
,接受一个C风格的字符串(const char *
),这样它就可以直接从a构造const char *
,而不经过禁止的额外转换
创建另一个重载greet
以接受一个std::string
.
另一方面,国际海事组织更清洁的替代方案就是保持现状; 调用者只需写
maher.greet(std::string("sam"));
Run Code Online (Sandbox Code Playgroud)