繁体   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