#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())的成员吗? 提前感谢您的回答。
答案 0 :(得分:2)
首先, inheriting from standard containers is a very bad idea 。
其次,我在您的代码中发现了许多问题:
过度使用动态内存:您在没有任何理由的地方使用new
。请注意,您的对是std::string
和int,即每对12个字节,具有公共std::string
实现(Asumming 32位架构)。指针的4个字节,std::string
用于保存字符串数组,4个字节用于字符串的大小计数器,4个字节用于字符串的int。所以没有理由在这里使用动态内存。如果您想共享所有权,请使用smart_pointer或std::reference_wrapper
之类的参考包装。
根据上述问题,过度使用容易出错的原始指针。正如我所说,智能指针是更好的选择。
最后,我认为由于slicing生成了编译器错误:std::map
在内部使用std::pair
来存储值。当您插入对时,该对被切片,因为std::map::insert
将const std::pair&
视为argumment,并且派生类的引用被隐式地呈现给基类的引用。
因此,正如编译器所说,该对(std::pair
)没有成员inc()
和dec()
。
您继承from std::pair
,而std::pair
继承自您的配对类。
考虑典型的继承示例:
class animal
{
void eat();
};
class dog : public animal
{
void bark();
};
这里的重点是狗是动物,但动物不是狗(并非所有动物都是狗)。所以狗可以吃,因为它是动物,而树皮因为它是狗。 但动物不能吠叫,因为从概念上讲它不是狗 因此,如果你看到一只狗好像只是一只动物,那么狗就不会吠叫。
答案 1 :(得分:0)
您使用auto
发现该类型(由begin
返回)是一张地图。
而地图没有公司。
也许实现std::begin( MyMap )
来检索正确的迭代器。
但你可能不应该衍生出来,而是更多地包装一对。