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

C++ 重载运算符返回对基类的引用,如何返回对派生类的引用?,c++,inheritance,C++,Inheritance,我有一个基本异常类,其中包括一个流式操作符: Base& Base::operator<<(const std::string& str); 在某个时刻,我创建并抛出一个从Base派生的类。比如: std::string myStr("foo bar"); throw Derived() << myStr; 这样做的最佳方式是什么?在投掷之前将底座向上抛到地面可以吗?我可以将基类更改为模板而不是定义这些派生类吗?[…]?问题出在throw关键字中,而不

我有一个基本异常类,其中包括一个流式操作符:

Base& Base::operator<<(const std::string& str);
在某个时刻,我创建并抛出一个从Base派生的类。比如:

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

这样做的最佳方式是什么?在投掷之前将底座向上抛到地面可以吗?我可以将基类更改为模板而不是定义这些派生类吗?[…]?

问题出在
throw
关键字中,而不是返回的引用中。引用同时指向基类和派生类。正是
throw
关键字使用声明的类型而不是要抛出的对象的多态类型。要抛出异常的多态类型,可以使用。您需要在基类中声明一个虚拟的
Raise()
方法,然后使用实现
throw*this重写派生类中的方法。在这种情况下,在派生类中,引用的声明类型
*此
将与其多态类型匹配,除非您忘记在某些派生类中重写
Raise()
方法。

问题在于
throw
关键字,而不是返回的引用中。引用同时指向基类和派生类。正是
throw
关键字使用声明的类型而不是要抛出的对象的多态类型。要抛出异常的多态类型,可以使用。您需要在基类中声明一个虚拟的
Raise()
方法,然后使用实现
throw*this重写派生类中的方法。在这种情况下,在派生类中,引用的声明类型
*此
将与其多态类型匹配,除非您忘记在某些派生类中重写
Raise()
方法。

我将稍微重新排列代码,以便插入运算符位于任何异常类之外

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;
}
类StringBuilder
{
公众:
模板

StringBuilder&operator我会稍微重新安排代码,以便插入操作符位于任何异常类之外

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;
}
类StringBuilder
{
公众:
模板
StringBuilder和操作员
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;
}