使用带有多态性的引用时初始化无效

时间:2013-12-04 14:45:39

标签: c++ reference compiler-errors g++ polymorphism

在处理我的一个项目时,我偶然发现了一个奇怪的编译器错误。我设法用这个小代码重现错误

#include <iostream>

class base
{
private:
    char f;
public:
    char get_char()
    {
    return f;
    }
    base(char f)
    {
    this->f = f;
    }
};


class derived : public base
{
private:
    std::string msg;
public:
    const std::string &get_message() const
    {
    return msg;
    }
    derived(const std::string& msg) : base(msg.c_str()[0])
    {
    this->msg = msg;
    }
};

void print_base(base &base_obj)
{
    std::cout << base_obj.get_char() << std::endl;
}


const char *input = "Hello World!";

int main(int argc, char* argv[])
{
    // This line compiles
    //derived d = derived(std::string(argv[0]));

    // This also works
    //derived d(argv[0]);

    // This line gives compiler error (see below)
    derived d(std::string(argv[0]));

    print_base(d);

    return 0;
}

不起作用的行给我编译错误:

ain.cpp: In function ‘int main(int, char**)’:
main.cpp:50:17: error: invalid initialization of non-const reference of type ‘base&’ from an rvalue of type ‘derived (*)(std::string*) {aka derived (*)(std::basic_string<char>*)}’
     print_base(d);
             ^
main.cpp:34:6: error: in passing argument 1 of ‘void print_base(base&)’
 void print_base(base &base_obj)

为什么第二种初始化方法没有编译?

附加信息:

编译器:g ++

3 个答案:

答案 0 :(得分:3)

derived d(std::string(argv[0]));

声明一个名为d的函数,该函数将指向std::string的指针作为参数。这是最令人烦恼的解析之一,因为它做了一些可能看起来不应该做的事情。它与

相同
derived d(std::string* argv);

要解决此问题,请忽略显式字符串构造,或使用大括号或双括号。

derived d(argv[0]);

derived d{std::string(argv[0])}; // C++11

derived d((std::string(argv[0])));    

答案 1 :(得分:3)

错误消息中的线索是:

from an rvalue of type ‘derived (*)(std::string*)

并表示您患有C ++ most vexing parse

答案 2 :(得分:2)

derived d(std::string(argv[0])); //function declaration (your code!)

相当于:

derived d(std::string argv[0]);

这是一个函数声明(不是对象声明)。

使用uniform-initialization-syntax来避免这样的问题:

derived d { std::string(argv[0]) }; //object declaration

希望有所帮助。