簡體   English   中英

在C ++中對std :: pair和std :: map進行子類化

[英]Subclassing std::pair and std::map in C++

    #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的一個實例,它會減少每個包含MyPairs的_ref成員函數。 如果MyPair中的_ref命中0,則表示不再引用它,因此它將自行刪除。

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

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

首先, 繼承標准容器是一個非常糟糕的主意

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

  • 過度使用動態內存:您在沒有任何理由的地方使用new 內存 請注意,您的對是std::string和int,即每對12個字節 ,具有常見的std::string實現(Asumming 32位體系結構)。 指針的4個字節, std::string用於保存char數組,4個字節用於字符串的大小計數器,4個字節用於該對的int。 所以沒有理由在這里使用動態內存 如果要共享所有權,請使用smart_pointer或std::reference_wrapper等引用包裝器。

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

最后,我認為你的編譯器錯誤是由於切片而產生的: std::map內部使用std::pair來存儲值。 插入對時,該對被切片, 因為std::map::insert const std::pair& as argumment,派生類的引用隱式地轉換為基類的引用
因此,正如編譯器所說,對( std::pair )沒有成員inc()dec()

你繼承from std::pair ,而不是std::pair繼承你的pair類 考慮一下tipical繼承示例:

class animal
{
    void eat();
};

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

這里的重點是狗是動物, 但動物不是狗 (並非所有動物都是狗)。 所以狗可以吃,因為它是動物,而樹皮因為它是狗。 但動物不能吠叫,因為從概念上講它不是狗
因此,如果你看到一只狗好像它只是一只動物, 狗就不會吠叫了

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

但你可能不應該衍生出來,而是更多地包裝一對。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM