作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设我有一个模板:
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++ - 希望虚拟仅作为重定向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4093024/
我是一名优秀的程序员,十分优秀!