I recently discovered a new application of the using
keyword; not with reference to the namespace
functionality but inside a derived class declaration. In my case this was pertinent in regards the issues surrounding the 'operator=' member-function.
I had a situation where, given the declarations:
class CString{
public:
...//Various functions.
operator=(const CString &cString)
{
//code to share internal array and increment reference count
}
operator=(const wchar_t *pstrString)
{
//code to create a personal internal array,
//resize it appropriately and copy the pstrString argument.
}
...
};
class CStringEx : public CString{
...//various members that expand upon CString's abilities.
};
...an object of CStringEx
did not work as I expected:
CStringEx cString;
cString=L"String contents";
Instead a compiler error was generated stating 'CStringEx has no 'operator=()' function that takes an argument of type wchar_t*' (or - very close - words to that effect). After quite a bit of study I learned this is because even the automatically compiler-generated operator=
member-functions of a derived class override those inherited from its parent class. This seems counter-intuitive and user-UNfriendly to me.
However, if I add a using
keyword:
class CStringEx : public CString{
public:
using CString::operator=;
...
};
...the child class will now use its parent's operator=
member function and all is well.
So far, so good. However, after further reading here and elsewhere I have learned that many programmers do not like to utilize using
for this purpose. For instance I have read some commentators who describe potentially unwanted side-effects, such as brining in ALL the operator= from the parent. However, again, other than in very specific circumstances I do not understand why inheriting all the parent member-functions would be and issue. If this is the major concern could someone explain the general dangers of doing so?
The only alternative I can think of is to write out stub functions in the child class for every operator=
member-function of it's parent and then explicitly call those respective member-functions:
class CStringEx : public CString{
public:
...
const CStringEx& operator=(const wchar_t* pstrString)
{
CString::operator=(pstrString);
return *this;
}
const CStringEx& operator=(const CString &cString)
{
CString::operator=(cString);
return *this;
}
...//and so on...
};
When compared to the version with using CString::operator=
this looks extremely ugly, cumbersome and messy to me. So again, why not use the using
keyword?
This is a bit subjective so let's review what we know:
If using
is the right tool for the job, then you should use it. That said:
using
will always bring in all the parent methods/operators, even newly added ones that you never intended. This might even result in broken code when someone creates a parent assignment operator that doesn't interact well with the child object.CStringEx
from a CString
but perhaps this is intended behavior.Given the fact that you're questioning it originally (based on things you've heard) and the points above, let's step back and look at your design a moment. The CStringEx
has two possibilities:
CString
objects.