问题
I have a lot of code here but I'm afraid this is as little code as I could put to convey the problem, so please bear with me:
#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);
}
The problem is with the line:
eat(*pCastFruit);
I'm getting the following errors:
- error C2385: ambiguous access of 'eat'
- error C3861: 'eat': identifier not found
I tried replacing the line with:
this->FruitEater<First>::eat(*pCastFruit);
The errors now changed to:
error LNK2019: unresolved external symbol "protected: virtual void __thiscall FruitEater::eat(class Apple const &)" (?eat@?$FruitEater@VApple@@@@MAEXABVApple@@@Z) referenced in function "private: bool __thiscall MultiFruitEater::dispatchEatByType(class Fruit const &)" (??$dispatchEatByType@VApple@@VOrange@@VBanana@@@?$MultiFruitEater@VApple@@VOrange@@VBanana@@@@AAE_NABVFruit@@@Z)
error LNK2019: unresolved external symbol "protected: virtual void __thiscall FruitEater::eat(class Banana const &)" (?eat@?$FruitEater@VBanana@@@@MAEXABVBanana@@@Z) referenced in function "private: bool __thiscall MultiFruitEater::dispatchEatByType(class Fruit const &)" (??$dispatchEatByType@VBanana@@@?$MultiFruitEater@VApple@@VOrange@@VBanana@@@@AAE_NABVFruit@@@Z)
Any ideas?
回答1:
Resolution:
So I got your reponse:
Using Your define ASSISTANCE : (as you gess the type you now send isn'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)
In your fruitEater class: (it let your multieater acccess to the eat methode
template<typename FruitType>
class FruitEater {
protected:
template<typename... Fruit> friend class MultiFruitEater;
virtual void eat(const FruitType & t) = 0;
};
How to use your new ASSISTANCE define:
ASINSTANCE(fruit, First, pCastFruit, eater) {
eater->eat(*pCastFruit);
return true;
}
Explanation: (not as precise as i would want)
I think the problem by doing this (this->FruitEater<First>::eat(*pCastFruit);
), is you force the compiler to use the FruitEater::eat() methode, wich is a virtual void...
来源:https://stackoverflow.com/questions/26351963/c-calling-a-virtual-method-from-a-multiply-inherited-template-class