假设我有一个模板:

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
airplanesAirplaneType指针的列表。

最佳答案

您需要另一个模板参数,因为您关心两个不同的类-指针的类型(以及要使用它调用的成员函数)以及容器的类型:

#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函数并没有真正使用containerlist这一事实,因此更明智的版本可能是:
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/

10-10 02:26