It's hidden out there!
Friday, 25. August 2006, 23:38:05
#include <iostream>
using std::cout;
using std::endl;
class X
{
public:
int Add(int)
{
cout << "X::Add(int)" << endl;
return 0;
}
int Add(X&)
{
cout << "X::Add(X&)" << endl;
return 0;
}
};
class D : public X
{
public:
int Add(char) // Hides base's Add method(s)
{
cout << "D::Add(char)" << endl;
return 0;
}
};
int main()
{
X x;
x.Add(x); // OK: X::Add(X&)
x.Add(3); // OK: X::Add(int);
D d;
d.Add('c'); // OK: D::Add(char)
d.Add(1); // Error: overloads are hidden
d.Add(x); // Error: overloads are hidden
return 0;
}
Derived classes have a bad attitude of hiding its bases' methods. It may sound weird, ugly and disturbing, but imagine otherwise; base class has changed, author decided to add another overload which has an argument type that is causing an unintentional conversion with the type you pass or by-passes your intentional conversion, for example?
If you really really want to reuse base's methods, here are tricks:
- Use "using" declaration to explicitly declare that derived class introduces base's types and methods to its declerative region (e.g. using X::Add). This will enable all overloads in base class to be visible to callers of derived.
- Explicitly refer to base's scope in the caller (e.g. d.X::Add(x) calls X::Add(X&))
- Implement overloads in derived, call base's methods.
- Templatize Derived::Add (e.g. template<typename T> int Add(T t) { return X::Add(t); } - you can specialize this as well!)
My heart beats for "using" and templatizing, although this is not the way I would prefer.
If I were to design this base class:
- Add would be a template.
- Since this class is designed to be a base, it could look like:
class D; template<typename T> class X { public: template<typename U> int Add(U u) { T* pt = static_cast<T*>(this); // force derived class to implement AddItem for each U return pt->AddItem(u); } }; // char, specialization. template<> template<> int X<D>::Add<char>(char c) { // add it return 0; }
- If it's not a template, it would probably have private pure virtual functions that needs to be implemented by derived types. (I've just heard some said "private pure virtual function? I thought we're talking about recent British-Pakistan cricket game!".)
class X
{
virtual int AddChar() = 0;
virtual int AddInt() = 0;
// .. others
public:
int Add(char c)
{
return AddChar();
}
};
If I were to write derived class:
- There will not be inheritance, but "pimpl".
class D /* : public X */
{
X* m_px;
public:
int Add(char c)
{
return m_px->Add(c);
}
}; - If there is an inheritance, I would use "using" to declare base's methods
- or, alternative to above case, I would use template methods and may be their specializations.
This all depends on design.








