Let’s say I have a template:
template <class N, class I>
void add(N* element, std::list<N*> & container, I (N::*f)() const,
std::string successmsg, std::string exceptmsg) {
//...
}
And I want to call it for a list of Base Class pointers to a derivative class.
add(newAirplane, airplanes, &Airplane::getRegistration,
"Added!", "Error: Existent!");
Airplane inherits from AirplaneType.
Of course, it doesn’t compile, N is first defined as AirplaneType and then as Airplane.
I added a virtual getRegistration @ AirplaneType but of course, the compiler gives out a vtable error.
What’s the proper way to solve this? AirplaneType has no registration attribute and I’m not interested in it having one. I also wanted to avoid virtual getRegistration() const {return "";}
Any suggestions for good practice?
EDIT:
Thanks for answers, but still not working. I think I have found the remaining problem, but not its solution:
void Airline::addAirplane(AirplaneType* airplane) {
add(newAirplane, airplanes, &Airplane::getRegistration,
"Added!", "Error: Existent!");
}
The type of pointer received is AirplaneType, not Airplane.
airplanes is a list of AirplaneType pointers.
You need another template parameter, because you care about two different classes – the type of the pointer (and hence the member function you’re going to call with it), and the type of the container:
In this case my
addfunction doesn’t really use the fact thatcontaineris alist, so a more sensible version might be:And then again, you could abstract further:
… but that’s slightly less convenient for the caller:
Any suggestions for good practice?
Don’t create containers of raw pointers.
Edit: to get this working with a virtual function, with each of my options:
Output is:
which shows that the override is correctly called even though the function pointer was taken to
AirplaneType::check, notAirplane::check.