2016-04-30 74 views
2

我有父類:地圖存儲派生的對象

class Data 
{ 
    public: 
     Data (void) { } 
     Virtual int Size (void) 
     { 
      return 100; 
     } 
    protected: 
     map<string, Data*> m; 

}; 

類從類繼承的數據:

class Struct : public Data 
{ 
    public: 
     Struct (void) { } 
     Struct & Add (const string & name, Data x) 
     { 
      Data * tmp = new Data (x); 
      m[name] = tmp; 
      return *this; 
     } 
     void Print (void) 
     { 
      for (const auto & tmp : m) 
       cout << tmp . first << " " << tmp . second -> Size() << endl; 
     } 
}; 

class IntData : public Data 
{ 
    public: 
     IntData (void) { } 
     int Size (void) 
     { 
      return 4; 
     } 
}; 

class DoubleData : public Data 
{ 
    public: 
     DoubleData (void) { } 
     int Size (void) 
     { 
      return 8; 
     } 

}; 

主:

int main (void) 
{ 
    Struct a; 
    a . Add ("Integer",IntData()); 
    a . Print(); 
    return 0; 
} 

Current output : Integer 100 
Expected output : Integer 4 

我想創建一個映射,它可以存放從Data類派生的各種類型的對象。但是當我想調用方法大小存儲對象在映射(在這種情況下IntData)應該返回4它總是從父類數據返回值。我該如何解決這個問題?

+0

你'Data'類需要虛析構函數。但更重要的是,多態只有在引用或指針作爲參數時才起作用。你的'Add'函數傳遞一個對象。谷歌「對象切片」。另外,發佈真正的代碼,因爲'虛擬'不是關鍵字。 – PaulMcKenzie

回答

4

有你的問題:

 Data * tmp = new Data (x); 

你把到地圖的實際指針是Data父類的一個實例。您正在拷貝構建一個新的Data父類的實例,該實例來自您按值傳遞的參數作爲參數。

您需要更改這個整體功能:

Struct & Add (const string & name, Data *x) 
    { 
     m[name] = x; 
     return *this; 
    } 

,主叫方現在是負責構建任何子類的新實例:

a . Add ("Integer",new IntData); 

那麼,這將作爲您預期。

當然,這種方法帶來了內存泄漏等各種問題,所以你最好使用std::shared_ptr。但是,這將是一個不同的問題...

+0

是的感謝您的答案,它現在正常工作,但有沒有辦法如何做到這一點,而不通過'新的IntData',只需通過'IntData()'就像我在我的代碼中? – kvway

+0

@kvway請閱讀我上面的評論。答案是「否」 - 多態性與引用和指針一起工作。通過值傳遞一個對象切片。 – PaulMcKenzie

+0

@kvway如果'Data'有一個虛擬的'clone'函數,'Add'通過引用接受'Data',那麼它可能是的,是的。但那你爲什麼想要? –

1

我已經爲你重寫你的代碼。

#include <unordered_map> 
#include <memory> 
#include <iostream> 

class Data { 
    public: 
     virtual ~Data(){} 
     virtual int Size() = 0; 
}; 

class Struct : public Data { 
      std::unordered_map<std::string, std::unique_ptr<Data>> m; 
    public: 
     Struct& Add(const std::string& name, std::unique_ptr<Data> x) { 
      m[name] = std::move(x); 
      return *this; 
     } 
     void Print() { 
      for(const auto& tmp : m) 
       std::cout << tmp.first << " " << tmp.second->Size() << "\n"; 
     } 
     int Size() override { 
      int sum = 0; 
      for (const auto& tmp : m) 
       sum += tmp.second->Size(); 
      return sum; 
     } 
}; 

class IntData : public Data { 
    public: 
     int Size() override { return 4; } 
}; 

class DoubleData : public Data { 
    public: 
     DoubleData() { } 
     int Size() override { return 8; } 
}; 

int main() { 
    Struct a; 
    a.Add("Integer", std::make_unique<IntData>()); 
    a.Print(); 
} 

Your welcome.

+0

請添加一些解釋,而不僅僅是代碼,使這個答案具有很高的價值 –