11

我正在学习 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;
}

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

4

4 回答 4

18

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

C++ 标准的 $5.2.7/1 起。

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

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

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

正如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;
}

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

于 2013-06-16T02:56:23.227 回答
5

您的问题不在于异常处理,而在于您的动态演员

'AA' is not a reference or pointer

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

所以你可以这样做:

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

...这将始终失败并引发std::bad_cast异常。

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

catch (std::bad_cast const& ex)

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

于 2013-06-16T02:57:16.650 回答
4

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

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

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

附带说明:像 g++ 这样的智能编译器也会发出警告:
warning: dynamic_caston an object (here a) can never succeed

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

于 2013-06-16T02:56:07.290 回答
4

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

就我而言,根本原因更为简单和平凡。

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

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

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

于 2016-08-16T18:50:57.737 回答