2015-04-29 199 views
2

我正在努力提供一組需要結構感知的序列化方法。因此,我構建了一個類模板,爲所有繼承它的類提供這些方法。覆蓋模糊繼承

這是我現在所擁有的:

template<typename T> 
class serializable 
{ 
    protected: 
     serializable() = default; 
    public: 
     size_t size_of() { return sizeof(T); } 
     void dump(void* data) { std::memcpy(data, this, serializable<T>::size_of()); } 
     void load(void* data) { std::memcpy(this, data, serializable<T>::size_of()); } 
     virtual void serialize() 
     { 
      std::cout << "Default serialize : size " << serializable<T>::size_of() << std::endl; 
     } 
}; 

struct point : public serializable<point> 
{ 
    float p[3]; 
}; 
struct particle : public point, public serializable<particle> 
{ 
    float v[3]; 
}; 

int main() 
{ 
    particle p; 
    p.serialize(); 

    return 0; 
} 

的問題是,調用p.serialize時,編譯器會發出serializable<point>::serialize()serializable<particle>::serialize()之間的曖昧過載錯誤。

我該如何解決這個問題?有什麼方法可以覆蓋從serializable<point>繼承只考慮serializable<particle>?我應該考慮另一種方法嗎?

+0

繼承在這裏看起來不太合適。粒子不是一個點。 –

+0

我試過'struct particle:public serializable {point p;點v; };'但是這會導致一個結構,如果大小爲56而不是48 ......並且我不能接受不對齊的數據 – Amxx

回答

5

你可以帶來你想要的serialize

struct particle : public point, public serializable<particle> 
{ 
    using serializable<particle>::serialize; 
    float v[3]; 
}; 

但是有可能你只是想用組成:

struct particle : public serializable<particle> 
{ 
    point p; 
    float v[3]; 
}; 
+0

我認爲組合實際上是最好的方法。你可以爲'particle'添加一個轉換運算符來返回'p'。 – jxh

+0

@jxh我同意。這就是爲什麼我說「可能」。不知道轉換操作符,但... – Barry

+0

只是一個想法。例如,它將涵蓋將'particle'傳遞給想要「點」參數的函數。 – jxh

3

我該如何解決這個問題?

覆蓋serialize()particle。無論如何,您需要序列化點數據和粒子自己的數據。來自基類的默認實現serialize將無法​​爲particle做正確的事情。

出於同樣的原因,您還需要覆蓋serialize()中的point

此外,我認爲使基類particle似乎不正確。 A particle不是point。它有一個位置和速度。聚合對我來說似乎是更好的方法。

struct point : public serializable<point> 
{ 
    void serialize() 
    { 
     // Serialize p 
     // ... 
    } 

    float p[3]; 
}; 

struct particle : public serializable<particle> 
{ 
    void serialize() 
    { 
     // Serialize location. 
     p.serialize(); 

     // Serialize velocity. 
     // ... 
    } 

    point p; 
    float v[3]; 
}; 

問題在serializable

serializable您的使用例子,在判斷線路:

void dump(void* data) { std::memcpy(data, this, serializable<T>::size_of()); } 
    void load(void* data) { std::memcpy(this, data, serializable<T>::size_of()); } 

會導致不確定的行爲。派生類不是TriviallyCopyable。在這種類型上使用std::memcpy會立即引發問題。

查看a question I had posted just last week的回答。

+0

我計劃在包含stl容器的指針的複雜結構中使用overiding序列化。然而,默認序列化的要點是使用'dump'將數據轉儲爲'char [size_of()]' – Amxx

+1

@Amxx,這會是一個問題,因爲這些類不是POD。你必須重新考慮你的策略。 sizeof(T)'不僅包含數據,還包含指向虛擬表的指針。 –

+0

在閱讀你的更新之後,我現在對什麼是和不是可以複製的問題進行了討論。我的想法是,包含std :: string/std :: vector /其他類似Synamic對象的結構,則必須覆蓋序列化函數。然而,我只是沒有得到如何可能是不安全的使用'std :: memcpy'結構像'point'這是正確的浮點數組......也試圖運行'std :: is_trivially_copyable',但編譯器說它不是std的成員(gcc 4.9.2/clang 3.6.0) – Amxx