It appears that what you want is for your Derived
class to support the following interface:
someInfo si;
someMoreInfo smi;
Base* pB = new Derived;
// Setting info
pB->setInfo(si); // Set the `Base::c` member of `*pB`
pB->setInfo(smi); // Set the `Derived::g` member of `*pB`
// Getting info
someInfo pB_si = pB->getInfo(); // Get `Base::c` from `*pB`
someMoreInfo pB_smi = pB->getInfo(); // Get `Derived::g` from `*pB`
Setting info: overloading
You’re actually correct that you don’t need setInfo
to be virtual
, because Derived::setInfo
doesn’t replace the Base
method; both are supposed to be accessible.
Unfortunately, as I’ve noted in a comment, by default Base::setInfo
gets hidden by Derived::setInfo
, regardless of the signature (!). Yes, this is surprising behavior; Scott Meyers notes in Effective C++ that this “surprises every C++ programmer the first time they encounter it” (Item 33 of the third edition).
Fortunately, the solution is simple. You need the using
keyword:
Class child: public Base{
// ... private members...
public:
using Base::setInfo;
void setInfo(someMoreInfo);
// .. rest of class...
};
This exposes the otherwise hidden name Base::setInfo
, permitting overload resolution to happen as if both versions of setInfo
were defined inside Derived
.
Getting info: return-dependent overload resolution
C++ does not support overloading on return types. You can easily check this:
class Foo
{
public:
int foo() { return 3; }
double foo() { return 83.4; }
};
Clang gives the following error (which is much more helpful than the GCC error):
error: functions that differ only in their return type cannot be overloaded
Now, you might ask, “why not?” Indeed, I know of at least one language, Perl, that supports different behavior based on the “context” in which an expression is evaluated.
This is actually pretty confusing (at least for those who aren’t fans of Perl, I guess). In general, programmers don’t expect different functions to be called depending on the context in which the function is called. And there are many contexts that don’t clearly indicate the expected return type:
std::cout << Foo().foo() << std::endl; // AMBIGUOUS!
… so there is simply no solution: you cannot differentiate two functions merely in their return type. You must provide different names for the two functions.
EDIT: If you really want, you could return-by-reference-argument:
void Base::getInfo(someInfo& si)
{
si = c;
}
void Derived::getInfo(someMoreInfo& smi)
{
smi = g;
}
Here, overload-resolution will be applied by checking the type of the argument passed to getInfo
, and no ambiguity is possible. This is one of the benefits of returning by reference-argument, though it’s debatable whether this is a superior to simply naming these more explicitly (I think explicit names would be preferable, and I think most programmers would agree).
solved do I need a virtual function