C++从多重继承的模板类中调用虚拟方法

C++ Calling a virtual method from a multiply inherited template class

本文关键字:调用 虚拟 方法 多重继承 C++      更新时间:2023-10-16

我这里有很多代码,但恐怕这是我能表达问题的最少量代码,所以请耐心等待:

#include <iostream>
#define ASINSTANCE(x, type, y)                                                 
    type * y = dynamic_cast<type *>(&(x));                                     
    if (y)
class Fruit {
    virtual void a() = 0; // This is to surpress the "Fruit isn't polymorphic" we'd otherwise get.
};
class Apple : public Fruit {
    virtual void a() {
    }
};
class Orange : public Fruit {
    virtual void a() {
    }
};
class Banana : public Fruit {
    virtual void a() {
    }
};
template<typename FruitType>
class FruitEater {
protected:
    virtual void eat(const FruitType & t) = 0;
};
template<typename... FruitTypes>
class MultiFruitEater : public FruitEater<FruitTypes>... {
public:
    // Eat any fruit if it belongs to FruitTypes (returns false otherwise).
    bool dispatchEat(const Fruit & fruit);
private:
    template<typename First>
    bool dispatchEatByType(const Fruit & fruit);
    template<typename First, typename Second, typename... Rest>
    bool dispatchEatByType(const Fruit & fruit);
};
class MyEater : public MultiFruitEater<Apple, Orange, Banana> {
protected:
    virtual void eat(const Apple & t);
    virtual void eat(const Orange & t);
    virtual void eat(const Banana & t);
};
void MyEater::eat(const Apple & t) {
    std::cout << "Ate apple." << std::endl;
}
void MyEater::eat(const Orange & t) {
    std::cout << "Ate orange." << std::endl;
}
void MyEater::eat(const Banana & t) {
    std::cout << "Ate banana." << std::endl;
}
template<typename... FruitTypes>
bool MultiFruitEater<FruitTypes...>::dispatchEat(const Fruit & fruit) {
    return dispatchEatByType<FruitTypes...>(fruit);
}
template<typename... FruitTypes>
template<typename First>
bool MultiFruitEater<FruitTypes...>::dispatchEatByType(const Fruit & fruit) {
    ASINSTANCE(fruit, const First, pCastFruit) {
        eat(*pCastFruit);
        return true;
    }
    return false;
}
template<typename... FruitTypes>
template<typename First, typename Second, typename... Rest>
bool MultiFruitEater<FruitTypes...>::dispatchEatByType(const Fruit & fruit) {
    ASINSTANCE(fruit, const First, pCastFruit) {
        eat(*pCastFruit);
        return true;
    }
    return dispatchEatByType<Second, Rest...>(fruit);
}
int main() {
    MyEater eater;
    Banana b;
    eater.dispatchEat(b);
}

问题出在线路上:

eat(*pCastFruit);

我得到以下错误:

  • 错误C2385:对"eat"的访问不明确
  • 错误C3861:"eat":找不到标识符

我试着用替换这条线

this->FruitEater<First>::eat(*pCastFruit);

错误现在更改为:

  • 错误LNK2019:未解析的外部符号"protected:virtualvoid __thiscall FruitEater::eat(class Apple const&)"(?吃@$FruitEater@VApple@@@@MAEXABVApple@@@Z)"private:boll__thiscall MultiFruitEater::dispatchEatByType(class Fruit const&)"($dispatchEatByType@VApple@@VOrange@@VBanana@@@$MultiFruitEater@VApple@@VOrange@@VBanana@@@@AAE_NABVFruit@@@Z)

  • 错误LNK2019:未解析的外部符号"protected:virtualvoid __thiscall FruitEater::eat(class Banana const&)"(?吃@$FruitEater@VBanana@@@@MAEXABVBanana@@@Z)函数"private:boll__thiscall MultiFruitEater::dispatchEatByType(类Fruitconst&)"($dispatchEatByType@VBanana@@@$MultiFruitEater@VApple@@VOrange@@VBanana@@@@AAE_NABVFruit@@@Z)

有什么想法吗?

分辨率:

所以我得到了你的回复:

使用您定义的ASSISTANCE:(因为您现在发送的类型不是常量

#define ASINSTANCE(x, type, y, eater)                                   
  const type * y = dynamic_cast<const type *>(&(x));                    
  FruitEater<type>* eater = dynamic_cast<FruitEater< type >*>(this);    
  if (y && eater)

在你的水果食客课上:(它让你的多食客学会了的饮食方法

template<typename FruitType>
class FruitEater {
 protected:
  template<typename... Fruit> friend class MultiFruitEater;
  virtual void eat(const FruitType & t) = 0;
};

如何使用您的新助理定义:

  ASINSTANCE(fruit, First, pCastFruit, eater) {
    eater->eat(*pCastFruit);
    return true;
  }

解释:(没有我想要的那么精确)

我认为这样做(this->FruitEater<First>::eat(*pCastFruit);)的问题是,你强迫编译器使用FruitEater::eat()方法,这是一个虚拟的void。。。