C++ - 希望虚拟仅作为重定向

标签 c++ class inheritance virtual

假设我有一个模板:

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 函数并没有真正使用 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/

相关文章:

c++ - C++ 的最佳(速度)任意精度库是什么?

c# - 无法在 Visual Studio 2013 中运行单元测试

c++ - 打印宏连接失败

javascript - jsp &lt;input&gt; 值未通过类 form-control 显示

java - 实现类似多态继承的行为

c++ - 继承和复制构造函数——如何从基类初始化私有(private)字段?

c++ - OpenCV imwrite 参数读取访问冲突

c++ - 静态类或实例指针

class - 'class' 与 'object' 相关,因为 'interface' 与 ...?

c# - 如何知道基类中的派生类