2012-05-23 74 views
2

这是超载ostream& operator<<派生类,而无需复制代码的基础类的唯一方法是什么?这些演员是不是应该避免的事情?超载的std :: ostream的&运算<<在派生类而不的static_cast <>

我没有看到任何其他方式,除了在基类中定义某种类型的函数,它将代表基类的数据,因为std :: operator < <可能“吃掉”了字符串?),为派生类执行相同的操作(当然,在派生类流中调用基类流表示函数。

什么是解决这个问题的理想解决方案?

#include <iostream> 

class Base 
{ 
    private: 
     int b_; 
    public: 
     Base() 
      : 
       b_() 
     {}; 

     Base (int b) 
      : 
       b_(b) 
     {}; 

     friend std::ostream& operator<<(std::ostream& os, const Base& b); 
}; 

std::ostream& operator<< (std::ostream& os, const Base& b) 
{ 
    os << b.b_; 
    return os; 
} 

class Derived 
: 
    public Base 
{ 
    private: 
     int d_; 
    public: 
     Derived() 
      : 
       d_() 
     {}; 

     Derived (int b, int d) 
      : 
       Base(b), 
       d_(d) 
     {}; 

     friend std::ostream& operator<<(std::ostream& os, const Derived& b); 
}; 

std::ostream& operator<< (std::ostream& os, const Derived& b) 
{ 
    os << static_cast<const Base&>(b) << " " << b.d_; 
    return os; 
} 



using namespace std; 


int main(int argc, const char *argv[]) 
{ 
    Base b(4); 

    cout << b << endl; 

    Derived d(4,5); 

    cout << d << endl; 

    return 0; 
} 
+0

您的解决方案有什么问题? –

+0

@ K-ballo他想避免我想的演员阵容。虽然它没有问题。 –

+0

@Seth Carnegie:为什么?演员出了什么问题?如何调用'operator <<'作为'Base'? –

回答

6

嗯......如果在结果未正确定义上下文内完成,但铸造成的基础始终是安全的,应避免铸造。

有可能通过考虑派生参考衰变为基本参考,以避免显式转换,所以你可以在这种情况下使用的隐式转换,如:

std::ostream& operator<< (std::ostream& os, const Derived& b) 
{ 
    const Base& bs = b; 
    os << bs << " " << b.d_; 
    return os; 
} 
+0

+1,因为你可以做我认为提问者真正想要的东西,以及避免强制转换的动机,只需更改最少的代码即可。也就是说,你会让编译器拒绝包含愚蠢错误的代码,比如像切换'Base'和'Derived'一样,这样一来,这个cast就是一个不安全的downcast而不是安全的upcast。 –

5
static_cast<const Base&>(b) 

是安全的,没有什么不正确的,因为每一个派生类对象也是基类对象,并且可以像一个处理。在一个鲁莽的方式使用时,才必须使用需要的地方去管型和以正确的方式,即通过语言标准的规定的根本目的

转换非常危险的。

1

你可以改变周围的事物,像这样的:

struct Base { 
    int b_; 
    void print(ostream &o) { o << b_; } 
}; 

struct Derived : Base { 
    int d_; 
    void print(ostream &o) { 
     Base::print(o); 
     o << ' ' << d_; 
    } 
}; 

ostream &operator<<(ostream &o, Base &b) { 
    b.print(o); 
    return o; 
} 

ostream &operator<<(ostream &o, Derived &d) { 
    d.print(o); 
    return o; 
} 

如果Base有虚函数(在这个例子事实并非如此),那么print可能是其中之一,你可以摆脱operator<<的多个重载的。

0

如果你不喜欢的类型转换,你可以有你的运营商呼叫writeTo功能正在使用该模板方法模式来实现。

例如

class Base { 
    public: 
     std::ostream& writeTo(std::ostream& ostr) const { os << b_; return this->doWriteTo(os); } 
    private: 
     int b_; 

     virtual std::ostream& doWriteTo(std::ostream& ostr) const = 0; // pure virtual 
}; 


class Derived { 
    private: 
     int d_; 
     virtual std::ostream& doWriteTo(std::ostream& ostr) const {return ostr << d_;} 
}; 

std::ostream& operator<<(std::ostream& ostr, const Derived& d) { 
    return d.writeTo(ostr); 

}

事实上,使用这种模式,你可以写operator<<一次,为Base所有:

std::ostream& operator<<(std::ostream& ostr, const Base& b) { 
    return b.writeTo(ostr); 

}

这个模式也elminates需要作出operator<<一个friend

相关问题