2009-11-26 168 views
2

我遇到了麻煩,試圖實現序列化我的遊戲中的某些類的功能。我將一些數據存儲在一個原始文本文件中,我希望能夠保存並加載它。 但是,這個細節是不相關的。問題是我試圖讓每個對保存文件感興趣的對象都能夠序列化自己。爲此,我定義了一個接口ISerializable,用運算符< <和operator >>的純粹虛擬聲明。非虛擬地使用虛擬繼承函數?

的類層次結構看起來像這樣

   -> GameObject -> Character -> Player ... 
ISerializable    -> Item -> Container ... 
       -> Room ... 

這意味着有序列化不同的類的對象很多可能發生的情況。例如,容器應該在所有包含物品上致電運營商< <。

現在,由於運營商>>是虛擬的,我想如果我想的東西序列化實現在ISerializable的定義我可以做這樣的事情

ostream & Player::operator<<(ostream & os){ 
    Character::operator<<(os); 
    os << player_specific_property 1 << " " 
     << player_specific_property 2 << "..."; 
    return os; 
} 

然後

ostream & Character::operator<<(ostream & os){ 
    GameObject::operator<<(os); 
    os << character_specific_property 1 << " " 
     << character_specific_property 2 << "..."; 
    return os; 
} 

功能但我很快就知道這第一次嘗試是非法的。我在這裏問的是我該如何解決這個問題

我不想爲每個類手動實現一個函數。我想我正在尋找類似於Java的super功能。

任何幫助表示讚賞。

- 評論上編輯 ------------

好了,上次我很着急,當我在寫這個問題。現在代碼更像是我試圖編譯它時的樣子。我解決了這個問題,我遇到的問題與問題無關。我很慚愧地說這是由於代碼大量重構之後出現錯誤而引起的,並且這個操作符在每個基類中都沒有實現。

非常感謝您的回覆!

回答

4

問題不在於你試圖虛擬調用虛函數。問題是這條線:os = Character::operator<<(os);。這是一項任務,但std::ostream沒有operator=

無論如何你都不需要任務。返回的流與傳入的流相同。它返回的唯一原因是您可以鏈接它們。

因此,解決方法是隻需更改代碼以

ostream & Player::operator<<(ostream & os){ 
    Character::operator<<(os); 
    os << player_specific_property 1 << " " 
     << player_specific_property 2 << "..."; 
    return os; 
} 
+1

其實還有一個問題是存在的......爭論順序顛倒了。您應該使用免費函數進行流式處理:'ostream&operator <<(ostream&,Player const&)',因爲在您的示例中,您將它們調用爲'player2 <<(player << os)',這是違反直覺的。 – 2009-11-26 17:30:03

+0

完全屬實,但我只修正了編譯問題,而不是概念性問題,從編輯的問題中可以明顯看出,根本原因實際上是洞察力的喪失。 – MSalters 2009-11-27 10:19:26

3

這不是如何重載操作< <爲ostream的作品。左邊的操作符是一個ostream(因此你必須將它重載爲一個自由函數),而右邊的操作符就是你的對象(這就是爲什麼虛擬機制不容易工作。

我想你可以嘗試:

class Base 
{ 
    //... 
    virtual std::ostream& output(std::ostream&) const; 
}; 

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

現在派生類中自然可以調用它的父(S)的輸出方法:

class Derived: public Base 
    //... 
    virtual std::ostream& output(std::ostream& os) const 
    { 
     Base::output(os); 
     return os << my_specific_data; 
    } 
};