错误:不能dynamic_cast ...(目标不是指针或引用)

foc*_*ard 10 c++ dynamic-cast exception try-catch

我正在学习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;
}
Run Code Online (Sandbox Code Playgroud)

所以我认为try catch将允许函数执行并向我显示异常的内容,但我的编译器不会编译它.我正在使用GNU GCC的代码块.请帮助我,告诉我我需要做什么才能按照我的意图运行代码.非常感谢.

Cap*_*ous 18

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

从+ 5.2.7/1的C++标准.

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

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

dynamic_cast<AA&>(a).aa();
//           ^^^ cast to reference.
Run Code Online (Sandbox Code Playgroud)

正如Johnsyweb指出的那样,当转换失败时,它dynamic_cast总会抛出std::bad_cast.虽然std::bad_cast从中得出std::exception它总是一个好主意,使用最符合预期失败条件的异常.这可以防止无意中将其他错误解释为不成功的强制转换.

要将此应用于您的示例,它可能看起来像下面的代码.

#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;
}
Run Code Online (Sandbox Code Playgroud)

[注意,using namespace std;强烈建议不要这样做,因为它可能会导致与全局命名空间中的标识符冲突.我在上面的例子中删除了它.]

  • @focusHard`bad_cast`位于`typeinfo`标题中.我已更新我的答案,包括对您的示例进行必要的更改.您应该做的另一件事是开始使用[cppreference.com](http://en.cppreference.com/w/cpp)作为参考.它列出了相关的头文件,并通常提供示例.在学习C++时,它可以提供很大的帮助. (2认同)

iam*_*ind 5

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

dynamic_cast<AA&>(a).aa();
Run Code Online (Sandbox Code Playgroud)

...并且您会抛出正确的异常。

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

因此最好限制此类代码的使用。在生产质量代码中,dynamic_cast应该仅对指针/引用执行。


Joh*_*web 5

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

'AA' is not a reference or pointer
Run Code Online (Sandbox Code Playgroud)

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

所以你可以这样做:

dynamic_cast<AA&>(a).aa();
Run Code Online (Sandbox Code Playgroud)

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

您应该捕获exception您期望的最具体类型,并且由于建议的方式catch是参考,您应该更喜欢:

catch (std::bad_cast const& ex)
Run Code Online (Sandbox Code Playgroud)

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


Lod*_*ijk 5

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

我的案例的根本原因更加简单和平凡。

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

我的例子的解决方案是包含我要转换到的类的头文件。

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