重载运算符返回对基类的引用,如何返回对派生类的引用?

时间:2015-12-07 16:51:12

标签: c++ inheritance

我有一个基本的异常类,其中包括(其中包括)流媒体操作符:

Button pdf = new Button("Print PDF");
        pdf.getElement().getStyle().setMarginRight(7, Unit.PX);
        pdf.addDomHandler(new ClickHandler(){
            @Override
            public void onClick(ClickEvent event) {
                //doing his job
            }}, ClickEvent.getType());

        Button edit = new Button("Ret");
        edit.getElement().getStyle().setMarginRight(7, Unit.PX);
        edit.addDomHandler(new ClickHandler(){
            @Override
            public void onClick(ClickEvent event) {
                //doing his job
                pdf.setEnabled(false); // error
            }}, ClickEvent.getType());

        Button ok = new Button("OK");
        ok.addDomHandler(new ClickHandler(){
            @Override
            public void onClick(ClickEvent event) {
                //doing his job
                pdf.setEnabled(true); //error
            }}, ClickEvent.getType());

此运算符返回Base& Base::operator<<(const std::string& str);

我有几个派生类看起来像:

*this

在某些时候,我创建并抛出一个派生自Base的类。类似的东西:

class Derived : public Base { };

我想使用以下方法捕获此异常:

std::string myStr("foo bar");
throw Derived() << myStr;

最好的方法是什么?扔掉它之前可以将Base强制转换为Derived吗?我可以将基类更改为模板而不是定义这些派生类吗? [...]?

2 个答案:

答案 0 :(得分:3)

问题出在throw关键字中,而不是在返回的引用中。该引用很好地指向了基类和派生类。它是throw关键字,它使用声明的类型而不是要抛出的对象的多态类型。要抛出异常的多态类型,可以使用Polymorphic Exception C++ idiom。您需要在基类中声明虚拟Raise()方法,然后使用实现throw *this;覆盖派生类中的方法。在这种情况下,在派生类中,声明的引用类型*this将匹配其多态类型,除非您忘记在某些派生类中重写Raise()方法。

答案 1 :(得分:1)

我会稍微重新排列你的代码,以便插入操作符在任何异常类之外。

class StringBuilder
{
public:
    template<class T>
    StringBuilder& operator<<(const T& t)
    {
        ss_ << t;
        return *this;
    }

    operator std::string() const
    {
        return ss_.str();
    }

private:
    std::stringstream ss_;
};

class Base : public std::runtime_error
{
    using runtime_error::runtime_error;
};

class Derived : public Base
{
    using Base::Base;
};

int main()
{
    try
    {
        throw Derived(StringBuilder() << "hello world");
    }
    catch(const Derived& e)
    {
        std::cout << "Derived\n";
    }
    catch(const Base& e)
    {
        std::cout << "Base\n";
    }
    return 0;
}