Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;抛出取消引用的指针_C++ - Fatal编程技术网

C++ C++;抛出取消引用的指针

C++ C++;抛出取消引用的指针,c++,C++,下面抛出的异常对象的类型是什么: 问题1>范围错误(“错误”);投掷r 回答1>范围错误的对象 问题2>异常*p=&r;投掷*p 回答2>异常的切片对象 问题3>异常*p=&r;投掷p Answer3>抛出指向范围_错误的指针。捕获处理可以通过动态绑定访问range_error成员函数 我对这些问题理解正确吗 //更新、编译并在VS2010上运行 #include <iostream> using namespace std; class ExClassA { public:

下面抛出的异常对象的类型是什么:

问题1>范围错误(“错误”);投掷r

回答1>范围错误的对象

问题2>异常*p=&r;投掷*p

回答2>异常的切片对象

问题3>异常*p=&r;投掷p

Answer3>抛出指向范围_错误的指针。捕获处理可以通过动态绑定访问range_error成员函数

我对这些问题理解正确吗

//更新、编译并在VS2010上运行

#include <iostream>
using namespace std;

class ExClassA
{
public:
    virtual void PrintMe() const
    {
        cout << "ExClassA" << endl;
    }
};

class ExClassB : public ExClassA
{
public:
    virtual void PrintMe() const
    {
        cout << "ExClassB" << endl;
    }
};

int main(int argc, char* argv[])
{   
    ExClassB exClassB;
    ExClassA *p = &exClassB;

    try
    {
        throw *p;
    }
    catch (const ExClassA& e)
    {
        e.PrintMe();        
    }

    try
    {
        throw p;
    }
    catch (const ExClassA* e)
    {
        e->PrintMe();
    }
}
#包括
使用名称空间std;
类感叹号
{
公众:
虚空PrintMe()常量
{

cout我认为你在这三个方面都是对的。抛出对象的类型(IIRC)是被抛出对象的静态类型。我必须深入标准一段时间才能找到确切的引号,但一个简单的例子似乎证实了这一点:

struct base {};
struct derived : base {};
void t() {
    derived d;
    base * b = &d;
    throw *b;
}
int main() {
    try {
        t();
    } catch ( derived const & ) {
        std::cout << "derived" << std::endl;
    } catch ( base const & ) {
        std::cout << "base" << std::endl;
    }
}
struct base{};
派生结构:基{};
void t(){
导出d;
基数*b=&d;
投掷*b;
}
int main(){
试一试{
t();
}捕获(派生常量&){

std::cout根据对象的静态类型,抛出对象总是导致抛出对象是您抛出对象的副本。因此,您的前两个答案是正确的


第三个比较复杂。如果
catch(range\u error*)
则不会捕获异常,因为类型不匹配。如果
catch(exception*)
您将无法在捕获的指针中访问
范围\u错误的成员;您可以
动态\u将该指针转换回范围\u错误指针。

所有三个答案都是正确的。请注意,您必须捕获一个 第三种情况下的指针类型

引发异常的常用方法是:

throw range_error("error");
在抛出站点上,您通常知道您所遇到的异常的确切类型 我想扔。我能想到的唯一例外是 异常作为参数传入,例如:

void f( std::exception const& whatToDoInCaseOfError )
{
    //  ...
    throw whatToDoInCaseOfError;  //  slices
}
这不是一个频繁的案例,但如果你想支持它,你需要一个 使用虚拟的
raise
功能:

class MyExceptions
{
public:
    virtual ~MyExceptions() {}
    virtual void raise() const = 0;
};

template<typename ExceptionType>
class ConcreteException : public ExceptionType, public MyExceptions
{
public:
    virtual void raise() const
    {
        throw *this;
    }
};
类MyExceptions
{
公众:
虚拟~MyExceptions(){}
虚空raise()常量=0;
};
模板
类ConcreteException:PublicExceptionType,PublicMyExceptions
{
公众:
虚空raise()常量
{
扔掉这个;
}
};
然后,客户机代码封装了他希望抛出的异常
ConcreteException
,您在其上调用
raise
函数,而不是
而不是直接调用
throw

参考:Lippman 17.1。这取决于你说“新”时的想法@Kerrek,我曾想过“新”可能会引起混淆,我已将其从OP中删除。相关标准见§15.1/3。@David,结构继承的默认修饰符是公共的吗?@q0987:
结构
之间的唯一区别是
类的默认访问说明符
私有的
,而for
结构的
是公共的。这既适用于继承,也适用于成员访问。此外,向局部变量抛出指针是错误的。RAII将清除该变量,指针将被删除DEAD@Bob好的一点是,我没有想到。捕获的异常是通常意义上的局部变量,还是很特殊mehow?这只会在抛出指针时出现,您只需确保指针指向有效的对象。当您按值(不是指针)抛出某个对象时所以捕获的异常是一个局部变量,它是抛出的异常的副本。@马克,你能检查我的更新吗?第二个try-catch打印的是我期望的内容,而不是你说的内容。@q0987,你在
ClassA
指针上调用一个虚拟函数,所以它的工作原理与任何其他变形相同ic指针。我在回答中的意思是,您无法访问对象中
ClassB
的任何非虚拟函数或数据成员。我们只需将代码从“throw whattodoincaseofer;”替换为“throw”为了避免切片问题。如果我没记错的话,以这种方式重试不会导致切片问题。@q0987但我们不能重试,除非我们在某个catch块中,在这种情况下,客户端不必传入异常。