Reputation: 5947
I just don't get it. Tried on VC++ 2008 and G++ 4.3.2
#include <map>
class A : public std::multimap<int, bool>
{
public:
size_type erase(int k, bool v)
{
return erase(k); // <- this fails; had to change to __super::erase(k)
}
};
int main()
{
A a;
a.erase(0, false);
a.erase(0); // <- fails. can't find base class' function?!
return 0;
}
Upvotes: 4
Views: 2252
Reputation: 6651
I agree with others' comments that you need to be very careful inheriting from STL classes, and it should almost always be avoided.
However, this problem could arise with some other base class from which it's perfectly sensible to inherit.
My question is: why not give your 2-argument function a different name? If it takes different arguments, presumably it has a slightly different meaning? E.g. erase_if_true or erase_and_delete or whatever the bool means.
Upvotes: 1
Reputation: 54325
To replace __super in a portable way, define a typedef at the top of your class like this:
typedef std::multimap<int, bool> parent;
public:
size_type erase(int k, bool v)
{
return parent::erase(k);
}
It does not need to be "parent" of course. It could be any name you like, as long as it is used consistently throughout your project.
Upvotes: 0
Reputation: 37443
Others have answered how to resolve the syntax problem and why it can be dangerous to derive from standard classes, but it's also worth pointing out:
Prefer composition to inheritance.
I doubt you mean for 'A' to explicitly have the "is-a" relationship to multimap< int, bool >. C++ Coding Standards by Sutter/Alexandrescu has entire chapter on this (#34), and Google points to many good references on the subject.
It appears there is a SO thread on the topic as well.
Upvotes: 3
Reputation: 14303
For those that use Effective C++ as a C++ programming reference, this issue is covered in Item 33 (Avoid hiding inherited names.) in the book.
Upvotes: 1
Reputation: 1862
Think whether you really want to inherit from std::map. In all the time I've written code, and that's longer than STL exists, I've never seen an instance where inheriting from a std::container was the best solution.
Specifically, ask yourself whether your class IS a multimap or HAS a multimap.
Upvotes: 5
Reputation: 247919
1: You need to be extremely careful when deriving from C++ standard library containers. It can be done, but because they don't have virtual destructors and other such niceties, it is usually the wrong approach.
2: Overload rules are a bit quirky here. The compiler first looks in the derived class, and if it finds any overload with the same name, it stops looking there. It only looks in the base class if no overloads were found in the derived class.
A simple solution to that is to introduce the functions you need from the base class into the derived class' namespace:
class A : public std::multimap<int, bool>
{
public:
using std::multimap<int, bool>::erase; // Any erase function found in the base class should be injected into the derived class namespace as well
size_type erase(int k, bool v)
{
return erase(k);
}
};
Alternatively, of course, you could simply write a small helper function in the derived class redirecting to the base class function
Upvotes: 18
Reputation: 12590
First of all, you should never derive from STL containers, because no STL containers define a virtual destructor.
Second of all, see Greg's answer about inheritance.
Upvotes: 6
Reputation: 1388
You've hidden the base class's erase member function by defining a function in the derived class with the same name but different arguments.
http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.9
Upvotes: 9
Reputation: 992947
When you declare a function in a class with the same name but different signature from a superclass, then the name resolution rules state that the compiler should stop looking for the function you are trying to call once it finds the first match. After finding the function by name, then it applies the overload resolution rules.
So what is happening is the compiler finds your implementation of erase(int, bool)
when you call erase(0)
, and then decides that the arguments don't match.
Upvotes: 26