假设我有一个模板:
template <class N, class I>
void add(N* element, std::list<N*> & container, I (N::*f)() const,
std::string successmsg, std::string exceptmsg) {
//...
}
我想称它为派生类的基类指针列表。
add(newAirplane, airplanes, &Airplane::getRegistration,
"Added!", "Error: Existent!");
Airplane
继承自AirplaneType
。当然,它不会编译,首先将N定义为
AirplaneType
,然后再定义为Airplane
。我添加了一个虚拟的
getRegistration
@ AirplaneType,但是当然,编译器会给出vtable错误。解决此问题的正确方法是什么?
AirplaneType
没有registration
属性,我对此不感兴趣。我也想避免virtual getRegistration() const {return "";}
有什么好的做法建议吗?
编辑:
感谢您的回答,但仍然无法正常工作。我想我已经找到了剩下的问题,但没有解决方案:
void Airline::addAirplane(AirplaneType* airplane) {
add(newAirplane, airplanes, &Airplane::getRegistration,
"Added!", "Error: Existent!");
}
收到的指针类型是
AirplaneType
,而不是Airplane
。airplanes
是AirplaneType
指针的列表。 最佳答案
您需要另一个模板参数,因为您关心两个不同的类-指针的类型(以及要使用它调用的成员函数)以及容器的类型:
#include <list>
struct AirplaneType {
};
struct Airplane : AirplaneType {
int check() const { return 3; }
};
template <typename T, typename U, typename I>
void add(T* element, std::list<U*> & container, I (T::*f)() const) {
container.push_back(element);
I i = (element->*f)();
}
int main() {
std::list<AirplaneType*> ls;
Airplane a;
add(&a, ls, &Airplane::check);
}
在这种情况下,我的
add
函数并没有真正使用container
是list
这一事实,因此更明智的版本可能是:template <typename T, typename U, typename I>
void add(T* element, U & container, I (T::*f)() const) {
container.push_back(element);
I i = (element->*f)();
}
然后再次,您可以进一步抽象:
template <typename T, typename U, typename AUF>
void add(T element, U & container, AUF func) {
container.push_back(element);
typename AUF::result_type i = func(element);
}
...但是这对于调用者来说不太方便:
#include <functional>
add(&a, ls, std::mem_fun(&Airplane::check));
有什么好的做法建议吗?
不要创建原始指针的容器。
编辑:使用我的每个选项,使它与虚函数一起工作:
#include <list>
#include <functional>
#include <iostream>
struct AirplaneType {
virtual int check() const { return 0; }
};
struct Airplane : AirplaneType {
int check() const { std::cout << "check\n"; return 3; }
};
template <typename T, typename U, typename I>
void add(U* element, std::list<T*> & container, I (U::*f)() const) {
container.push_back(element);
I i = (element->*f)();
}
template <typename T, typename U, typename AUF>
void add2(T element, U & container, AUF func) {
container.push_back(element);
typename AUF::result_type i = func(element);
}
int main() {
std::list<AirplaneType*> ls;
Airplane a;
add(static_cast<AirplaneType*>(&a), ls, &AirplaneType::check);
add2(&a, ls, std::mem_fun(&AirplaneType::check));
}
输出为:
check
check
这表明即使函数指针指向了
AirplaneType::check
而不是Airplane::check
,也正确调用了覆盖。关于c++ - C++-希望虚拟仅充当重定向,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4093024/