0
    #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 からクラスをサブクラス化しました。「マイペア」と名付けました。また、std::map からサブクラス化し、「MyMap」と名付けました。そのため、新しい MyPair を MyMap に挿入するたびに、MyPair の inc() メンバー関数が呼び出されるため、MyPair は参照のカウンターである _ref メンバーをインクリメントします。MyMap のインスタンスを削除すると、含まれている各 MyPairs のすべての _ref メンバー関数が減少します。MyPair の _ref が 0 になった場合は、参照されなくなったことを意味するため、自身を削除します。

上記のコードが機能するのは、MyMap でコードのいくつかの行にコメントを付けることができたからです。それらのコメントを外すと、メイン関数に MyPair インスタンスを挿入しても、 std::pair に inc() や dec() のようなメンバーがないというエラーがコンパイラから返されます。単なる std::pair ではなく、これらのメンバーを含む MyPair インスタンスを挿入したことをコンパイラが認識しないことはわかっています。

MyMap 内で MyPair(inc() and dec()) のメンバーを呼び出す方法はありますか? 事前にご回答いただきありがとうございます。

4

2 に答える 2

2

まず第一に、標準コンテナからの継承は非常に悪い考えです。

次に、あなたのコードには多くの問題があります。

  • 動的メモリの過剰使用:newまったく理由のない場所で使用しています。std::stringペアは ofと int であることに注意してください。つまり、共通の実装 (32 ビット アーキテクチャを想定) ではペアあたり 12 バイトです。std::stringchar 配列を保持するために使用するポインターのstd::string4 バイト、文字列のサイズ カウンター用の 4 バイト、およびペアの int 用の 4 バイト。したがって、ここで動的メモリを使用する理由はありません。所有権を共有したい場合は、smart_pointer または のような参照ラッパーを使用しますstd::reference_wrapper

  • 上記の問題に続いて、エラーが発生しやすい raw-pointers の過剰使用。前述したように、スマート ポインターはより優れた代替手段です。

最後に、スライスが原因でコンパイラエラーが生成されたと思います: 内部的に値を保存するためにstd::map使用します。std::pairペアを挿入すると、そのペアがスライスされます。これは、std::map::insert引数const std::pair&としての観点と、派生クラスの参照が基本クラスの参照に暗黙的にキャストされるためです。
したがって、コンパイラが言うように、ペア ( std::pair) にはメンバーinc()とがありませんdec()

あなたはペアクラスから継承しているのfrom std::pairではなくstd::pair、継承しています。典型的な継承の例を考えてみましょう:

class animal
{
    void eat();
};

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

ここでのポイントは、犬は動物ですが、動物は犬ではないということです(すべての動物が犬であるとは限りません)。犬は動物だから食べられるし、犬だから吠える。しかし、概念的には犬ではないため、動物は吠えません
したがって、犬をただの動物であるかのように見ると、犬は吠えません

于 2013-09-01T20:15:00.520 に答える
0

which を使用autoすると、型 ( によって返されるbegin) がマップであることがわかります。そして地図には株式会社がありません。std::begin( MyMap )適切なイテレータを取得するために実装するかもしれません。

しかし、おそらく派生させず、さらにペアをラップする必要があります。

于 2013-09-01T17:01:45.417 に答える