2013-09-01 90 views
-1
#include <iostream> 
    #include <string> 
    #include <utility> 
    #include <map> 

    using namespace std; 

    class MyPair: public pair<string, int> 
    { 
     int _ref; 
    public: 
     MyPair(): pair<string, int>(), _ref(0) {} 
     MyPair(string arg1, int arg2): pair<string, int>(arg1, arg2), _ref(0) {} 
     ~MyPair(); 
     void inc() { 
      _ref++; 
     } 
     void dec() { 
      _ref--; 
      if (_ref == 0) delete this; 
     } 
    }; 

    class MyMap: public map<string, int> 
    { 
    public: 
     MyMap(): map<string, int>() {} 
     MyMap(const map<string, int>& mp): map<string, int>(mp) { 
      //for(auto i=begin(); i!=end(); ++i) i->inc(); 
      //I want to perform that instruction above, but it gives me an error 
     } 
     ~MyMap() { 
      //for(auto i=begin(); i!=end(); i++) i->dec(); 
      //same as here 
     } 
     void insertNewPair(MyPair * mypair) { 
      insert(*mypair); 
      mypair->inc(); 
     } 
    }; 

    int main(int argc, char **argv) 
    { 
     MyMap mymap; 
     mymap.insertNewPair(new MyPair("1", 1)); 
     mymap.insertNewPair(new MyPair("2", 2)); 
     cout << "mymap[\"1\"] = " << mymap["1"] << endl; 
     cout << "mymap[\"2\"] = " << mymap["2"] << endl; 
     return 0; 
    } 

我從std :: pair中繼承了一個類,以便我可以在其中附加一個引用計數器。我將它命名爲「MyPair」。我也從std :: map分類,並將其命名爲「MyMap」。因此,每次我在MyMap中插入新的MyPair時,都會調用MyPair的inc()成員函數,這樣MyPair就會增加其參考計數器的_ref成員。如果我刪除了MyMap的一個實例,它將遞減其包含的每個MyPair的所有_ref成員函數。如果MyPair中的_ref達到0,這意味着它不再被引用,所以它會自己刪除。在C++中繼承std :: pair和std :: map

上面的代碼有效,因爲我設法在MyMap中註釋了一些代碼行。當我取消註釋它們時,編譯器給我一個錯誤,說std :: pair沒有像inc()和dec()這樣的成員,即使我在主函數中插入MyPair實例。我知道編譯器沒有注意到我插入了包含這些成員的MyPair實例,而不僅僅是一個普通的std :: pair。

有沒有辦法可以在MyMap中調用MyPair(inc()和dec())的成員? 感謝您提前回答。

+9

從它們派生出來已經夠糟糕了。公開這樣做是在尋求麻煩。 – chris

+0

試着更清楚地解釋你在做什麼。你只是想創建一個引用計數對。 (這5個字總結你的段落)也試圖顯示什麼不工作清楚。 (這裏顯示編譯器的錯誤,並讓代碼像你一樣評論什麼是錯誤的) – dzada

+0

正如已經解釋過的這個os非常糟糕的代碼。我建議你閱讀一些關於C++的書,比如Effective C++,Effective STL和其他類似的書。現代C++擁有所有的工具,所以沒有ne會寫這樣的代碼。 – Phil1970

回答

2

首先,inheriting from standard containers is a very bad idea

其次,我看到你的代碼中的許多問題:

  • 過度使用動態內存:您正在使用的地方,其中new沒有任何道理可言。請注意,您的配對是std::string和int,即每對12個字節與普通的std::string實現(Asumming 32位體系結構)。 std::string用於保存char數組的指針的4個字節,字符串的大小計數器的4個字節以及該對的int的4個字節。所以沒有理由在這裏使用動態內存。如果您想分享所有權,請使用smart_pointer或參考包裝,如std::reference_wrapper

  • 從以上問題出發,過度使用易出錯的原始指針。正如我所說的,智能指針是一個更好的選擇。

最後,我認爲是由於slicing產生編譯器錯誤:std::map使用std::pair內部存儲的值。當插入一對時,該對被切片,,因爲std::map::insertconst std::pair&看作是argumment,並且派生類的引用被隱式地轉換爲基類的引用。
因此,正如編譯器所說,該對(std::pair)沒有成員inc()dec()

您正在繼承from std::pair而非std::pair繼承自您的配對類。 考慮tipical繼承示例:

class animal 
{ 
    void eat(); 
}; 

class dog : public animal 
{ 
    void bark(); 
}; 

這裏的要點是狗是動物,但動物不是狗(並非所有的動物是狗)。所以狗可以吃,因爲它是一種動物,因爲它是一隻狗而吠叫。 但動物不能叫,因爲從概念上說它不是狗
所以,如果你看到一隻狗,就好像它只是一隻動物一樣,狗不會樹皮

+0

謝謝。這是非常豐富的。稍後我會做你的建議(使用std :: reference_wrapper)。但是我認爲如果我要創建自己的容器,我會讓自己的程序變得很慢,這就是爲什麼我選擇從std :: map子類化並利用它在查找關鍵值時實現的搜索算法的優勢。再次感謝你的幫助。 –

0

您使用auto發現該類型(由begin返回)是一張地圖。 而地圖沒有公司。 也許執行std::begin(MyMap)來檢索正確的迭代器。

但是你應該可以不衍生,並且更多地包裝一對。