我正在学习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的代码块。请帮助我,告诉我我需要做什么才能按照我的意图运行代码。非常感谢。
答案 0 :(得分:18)
dynamic_cast
只能转换为指针值或引用,这正是错误告诉你的。
来自C ++标准的5.2.7 / 1美元。
表达式dynamic_cast&lt;的结果T>(v)是将表达式v转换为类型T的结果.T应该是指向完整类类型的指针或引用,或者是“指向cv void的指针”。
为了使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;
这样的操作,因为它可能会导致与全局命名空间中的标识符冲突。我在上面的示例中删除了它。]
答案 1 :(得分:5)
您的问题不在于异常处理,而在于动态广告:
'AA' is not a reference or pointer
dynamic_cast
安全地将指针和引用转换为class
es而非实例。
所以你可以这样做:
dynamic_cast<AA&>(a).aa();
... 总是失败并抛出std::bad_cast
例外。
您应该抓住您期望的最具体的exception
类型,而the recommended way to catch
is by reference,您应该更喜欢:
catch (std::bad_cast const& ex)
答案 2 :(得分:4)
您收到编译错误,因为您的dynamic_cast
不在指针或引用上
将其更改为:
dynamic_cast<AA&>(a).aa();
...你得到了正确的异常抛出。
侧面说明:像g ++这样的智能编译器也会发出警告:
警告:dynamic_cast
对象(此处a
)永远无法成功。
所以最好限制这些代码来玩弄。在生产质量代码中,dynamic_cast
应仅在指针/引用上执行。
答案 3 :(得分:3)
我刚刚处理了同样的错误,但在我的情况下,我是从指针指向指针,所以这里的其他答案不适用。我的错误消息略有不同,但是: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;
向前声明,导致它存在但不完整,因此错误。
我的解决方案是包含我正在投射的类的头文件。
这不是上面的问题提问者,但我的情况可以看出可以产生相同类型的错误。