#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;
}
I subclassed a class from std::pair so that I can append a reference counter in it. I named it "MyPair". I also subclassed from std::map and I named it "MyMap". So that everytime I insert new MyPair in MyMap, it calls the inc() member function of MyPair, so that MyPair would increment its _ref member which is the counter of its reference. If I delete an instance of MyMap, it decrements all the _ref member function of each of its contained MyPairs. If _ref in MyPair hits 0, it means that it was no longer referenced, so it will delete itself.
That code above works, because I managed to comment some lines of codes there in MyMap. When I uncomment them, the compiler gives me an error that says that std::pair has no members like inc() and dec(), even though I insert MyPair instances there at the main function. I know that the compiler doesn't notice that I inserted MyPair instances that contains those members, not just a plain std::pair.
Is there's a way that I can call those members of MyPair(inc() and dec()) inside MyMap? Thanks for your answers in advance.
First of all, inheriting from standard containers is a very bad idea .
Secondly, I see many problems in your code:
Overuse of dynamic memory: You are using new
in places where there is no reason at all. Note that your pair is of std::string
and int, that is, 12 bytes per pair with a common std::string
implementation (Asumming 32 bits architecture). 4 bytes of the pointer which std::string
uses to hold the char array, 4 bytes for the size counter of the string, and 4 bytes for the int of the pair. So there is no reason to use dynamic memory here . If you want to share ownership, use a smart_pointer or a reference wrapper like std::reference_wrapper
.
Following from the problem above, overuse of error-prone raw-pointers . As I said, smart pointers are a better alternative.
Finally, I think your compiler error is generated due to slicing : std::map
uses std::pair
internally to store the values. When you insert your pair, that pair is sliced, because std::map::insert
espects const std::pair&
as argumment and a reference of a derived class is casted implicitly to a reference of a base class .
So, as the compiler says, the pair ( std::pair
) has no members inc()
and dec()
.
You are inheriting from std::pair
, not std::pair
is inheriting from your pair class . Consider the tipical inheritance example:
class animal
{
void eat();
};
class dog : public animal
{
void bark();
};
The point here is the dog is an animal, but the animal is not a dog (Not all animals are dogs). So the dog can eat because it is an animal, and bark because its a dog. But the animal can't bark, because conceptually its not a dog .
So if you see a dog as if it was an animal only, the dog cannot bark .
You use auto
which finds out that the type (returned by begin
) is a map. And map has no inc. Maybe implement std::begin( MyMap )
to retrive the right iterator.
But You should probably not derivate, and more wrap a pair.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.