12

鉴于此示例代码:

#include <iostream>
#include <stdexcept>

class my_exception_t : std::exception
{
public:
    explicit my_exception_t()
    { }

    virtual const char* what() const throw()
    { return "Hello, world!"; }
};

int main()
{
    try
        { throw my_exception_t(); }
    catch (const std::exception& error)
        { std::cerr << "Exception: " << error.what() << std::endl; }
    catch (...)
        { std::cerr << "Exception: unknown" << std::endl; }

    return 0;
}

我得到以下输出:

Exception: unknown

然而,简单地继承my_exception_tfrom std::exception public,我得到以下输出:

Exception: Hello, world!

有人可以向我解释为什么在这种情况下继承类型很重要吗?标准中参考的奖励积分。

4

2 回答 2

21

当您私有继承时,您不能转换为或以其他方式访问该类之外的该基类。既然您从标准中要求了一些东西:

§11.2/4:
如果基类的发明公共成员是可访问的,则称基类是可访问的。如果基类是可访问的,则可以将指向派生类的指针隐式转换为指向该基类的指针(4.10、4.11)。

简单地说,对于类之外的任何东西,它就像你从未继承自std::exception,因为它是私有的。因此,它将无法被捕获在std::exception&子句中,因为不存在转换。

于 2010-04-03T00:15:30.950 回答
10

有人可以向我解释为什么在这种情况下继承类型很重要吗?标准中参考的奖励积分。

继承的类型无关紧要。重要的是您有一个可用于其中一种捕获类型的可访问转换。碰巧的是,由于它不是公共继承,因此没有公共可访问的转换。


解释:

您可以在此处看到相同的行为:

class B
{
};

class C1 : B
{
};

class C2 : public B
{
};

int main(int argc, char** argv)
{
    B& b1 = C1();//Compiling error due to conversion exists but is inaccessible
    B& b2 = C2();//OK
    return 0;
}

抛出的异常仅在以下情况下被 catch 块捕获:

  1. catch 块有一个匹配的类型,或者
  2. catch 块用于具有可访问转换的类型
  3. catch 块是一个 catch(...)
于 2010-04-03T00:13:07.697 回答