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

invalid initialization when using references with polymorphism

本文关键字:引用 初始化 无效 多态性      更新时间:2023-10-16

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

#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++

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])));    

错误消息中的线索是:

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

并表示您正遭受C++最麻烦的解析

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

相当于:

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

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

使用统一的初始化语法来避免这样的问题:

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

希望能有所帮助。