2013-09-01 85 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)来检索正确的迭代器。

但是你应该可以不衍生,并且更多地包装一对。