为什么c ++在尝试将其转换为另一种类型时不能识别字符串?

时间:2011-09-10 15:02:35

标签: c++ casting

我有一个相当简单的类,如下所示:

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对象这一事实有关?

6 个答案:

答案 0 :(得分:6)

maherconst char[6],而samconst 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::stringPerson,以便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;
};