C++ 错误:无法动态转换...(目标不是指针或引用)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17129728/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:57:03  来源:igfitidea点击:

error: cannot dynamic_cast ... (target is not pointer or reference)

c++exceptiontry-catchdynamic-cast

提问by focusHard

I'm learning exception handling in C++ and run into a problem. Here's the code:

我正在学习 C++ 中的异常处理并遇到问题。这是代码:

#include<iostream>
#include<exception>

using namespace std;

class A
{
public:
    virtual void f(void){}
};

class AA:public A
{
public:
    void aa(void){};

};

int main(void)
{

    A a;
    try
    {
        dynamic_cast<AA>(a).aa();
    }
    catch(exception ex)
    {
        cout<<"["<<ex.what()<<"]"<<endl;
    }
    return 0;
}

So I thought the try catch will allow the function to execute and show me the content of the exception, but my compiler does not compile it. I'm using codeblock with GNU GCC. Please help me and show me what I need to do to get the code run as I intended. thanks a lot.

所以我认为 try catch 将允许函数执行并向我显示异常的内容,但我的编译器没有编译它。我在 GNU GCC 中使用代码块。请帮助我并告诉我我需要做什么才能使代码按预期运行。多谢。

回答by Captain Obvlious

dynamic_castcan only cast to a pointer value or reference, which is exactly what the error is telling you.

dynamic_cast只能转换为指针值或引用,这正是错误告诉您的。

From $5.2.7/1 of the C++ Standard.

从 C++ 标准 5.2.7/1 美元起。

The result of the expression dynamic_cast< T >(v) is the result of converting the expression v to type T. T shall be a pointer or reference to a complete class type, or “pointer to cv void.”

表达式 dynamic_cast< T >(v) 的结果是将表达式 v 转换为类型 T 的结果。 T 应是指向完整类类型的指针或引用,或“指向 cv void 的指针”。

In order for dynamic_castto throw an exception when the object cannot be converted you need to cast to a reference. Change it to the following:

为了dynamic_cast在对象无法转换时抛出异常,您需要转换为引用。将其更改为以下内容:

dynamic_cast<AA&>(a).aa();
//           ^^^ cast to reference.

As Johnsywebpointed out dynamic_castwill always throw std::bad_castwhen the conversion fails. Although std::bad_castis derived from std::exceptionit is always a good idea to use the exception which best fits the expected fail condition. This prevents inadvertently interpreting other errors as an unsuccessful cast.

正如Johnsyweb指出的那样,转换失败时dynamic_cast总是会抛出std::bad_cast。尽管std::bad_cast源自std::exception它,但使用最适合预期失败条件的异常总是一个好主意。这可以防止无意中将其他错误解释为不成功的转换。

To apply this to your example it might look like the code below.

要将其应用于您的示例,它可能类似于下面的代码。

#include <iostream>
#include <typeinfo> // std::bad_cast

class A
{
public:
    virtual void f(void){}
};

class AA:public A
{
public:
    void aa(void){};
};

int main(void)
{
    A a;

    try
    {
        dynamic_cast<AA&>(a).aa();
    }
    catch(const std::bad_cast& ex)
    {
        std::cout << "["<<ex.what()<<"]" << std::endl;
    }
    return 0;
}

[Note, doing things like using namespace std;is strongly discouraged as it can cause conflicts with identifiers in the global namespace. I have removed it in the example above.]

[注意,using namespace std;强烈建议不要这样做,因为它会导致与全局命名空间中的标识符发生冲突。我已在上面的示例中将其删除。]

回答by Johnsyweb

Your problem is not with exception handling, but with your dynamic cast:

您的问题不在于异常处理,而在于您的动态转换

'AA' is not a reference or pointer

dynamic_castsafely converts pointersand referencesto classes and not instances.

dynamic_cast安全地将指针引用转换为classes 而不是实例

So you could do:

所以你可以这样做:

dynamic_cast<AA&>(a).aa();

...which will alwaysfail and throw a std::bad_castexception.

...它总是会失败并抛出std::bad_cast异常。

You should catch the most-specific type of exceptionthat you are expecting and since the recommended way to catchis by reference, you should prefer:

您应该捕获exception您期望的最具体的类型,并且由于推荐的方法catch是 by reference,您应该更喜欢:

catch (std::bad_cast const& ex)

Further reading:dynamic_cast conversionon cppreference.com.

进一步阅读:cppreference.com上的dynamic_cast 转换

回答by iammilind

You are getting a compiler error because your dynamic_castis not on pointer or reference.
Change it to:

您收到编译器错误,因为您dynamic_cast不在指针或引用上。
将其更改为:

dynamic_cast<AA&>(a).aa();

... and you get the proper exception thrown.

...你会得到正确的异常抛出。

On side note: Smart compilers like g++ would warn as well:
warning: dynamic_caston an object (here a) can never succeed.

旁注:像 g++ 这样的智能编译器也会发出警告:
warning: dynamic_caston an object (here a) can never success

So it's better to limit such code for toying around. In production quality code, the dynamic_castshould be performed only on pointer/reference.

所以最好限制这样的代码来玩弄。在生产质量代码中,dynamic_cast应该只在指针/引用上执行。

回答by Loduwijk

I just dealt with the same error, but in my case I was going from a pointer to a pointer, so the other answers here did not apply. My error message was slightly different, however: error: cannot dynamic_cast 'f()' (of type 'class B*') to type 'class A*' (target is not pointer or reference to complete type).

我刚刚处理了同样的错误,但在我的情况下,我是从一个指针到一个指针,所以这里的其他答案不适用。但是,我的错误消息略有不同:error: cannot dynamic_cast 'f()' (of type 'class B*') to type 'class A*' (target is not pointer or reference to complete type).

The root cause in my case was much more simple and mundane.

在我的案例中,根本原因要简单得多。

Notice the addition of to complete typeat the end. This caused me to remember that I did not include the header file for my class which I was using. It was not an unknown symbol because A*was forward declared with class A;in the header file, causing it to exist but not be complete, hence the error.

注意最后添加了to complete 类型。这让我想起我没有包含我正在使用的类的头文件。它不是未知符号,因为在头文件中使用了A*向前声明class A;,导致它存在但不完整,因此出现错误。

The solution in my case was to include the header file for the class I was casting to.

在我的情况下,解决方案是包含我要转换到的类的头文件。

This is not the question asker's problem above, but as can be seen by my case can generate the same type of error.

这不是上面的提问者的问题,但从我的案例中可以看出可能会产生相同类型的错误。