2012-05-23 63 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

相關問題