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

时间:2014-10-14 03:00:41

标签: c++ templates multiple-inheritance variadic-templates

我这里有很多代码,但我担心这个问题的代码很少,所以请耐心等待:

#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:virtual void __thiscall FruitEater :: eat(class Apple const&amp;)“ (?吃@?$ FruitEater @ VApple @@@@ MAEXABVApple @@@ Z)在功能中引用 “private:bool __thiscall MultiFruitEater :: dispatchEatByType(class fruit const&amp;)” (?? $ dispatchEatByType @ @@ VApple @@ VOrange @@@ VBanana?$ MultiFruitEater @ @@ VApple @@ VOrange @@@@ VBanana @@@ AAE_NABVFruit Z)

  • 错误LNK2019:未解析的外部符号“protected:virtual void __thiscall FruitEater :: eat(class Banana const&amp;)“ (?吃@?$ FruitEater @ VBanana @@@@ MAEXABVBanana @@@ Z)在 函数“private:bool __thiscall MultiFruitEater :: dispatchEatByType(类Fruit const&amp;)“ (?? $ dispatchEatByType @ VBanana @@@?$ MultiFruitEater @ @@ VApple @@ VOrange @@@@ VBanana @@@ AAE_NABVFruit Z)

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

分辨率:

所以我得到了你的回应:

使用你的定义ASSISTANCE :(当你发现你现在发送的类型不是&#t; const

#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)

在你的fruitEater课程中:(它让你的多重播放器符合吃方法

template<typename FruitType>
class FruitEater {

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

};

如何使用新的ASSISTANCE定义:

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

说明:(不如我想要的那么精确)

我认为执行此操作(this->FruitEater<First>::eat(*pCastFruit);)的问题是,您强制编译器使用FruitEater :: eat()方法,这是一个虚拟的空白......