As Stefaan says, this can be achieved with double dispatch with additional fixtures:
#include <iostream>
class Derived1;
class Derived2;
class ParamType
{
public:
virtual void invertFunc (const Derived1& deriv) const = 0;
virtual void invertFunc (const Derived2& deriv) const = 0;
};
class DerivedParamType1;
class DerivedParamType2;
class Base
{
public:
virtual void func (const ParamType& param) const = 0;
virtual void func (const DerivedParamType1& param) const
{
throw std::runtime_error ("Can not accept DerivedParamType1");
}
virtual void func (const DerivedParamType2& param) const
{
throw std::runtime_error ("Can not accept DerivedParamType2");
}
};
class Derived1 : public Base
{
public:
void func (const ParamType& param) const
{
param.invertFunc (*this);
}
void func (const DerivedParamType1& param) const
{
std::cout << "Derived1::func (DerivedParamType1)" << std::endl;
}
};
class Derived2 : public Base
{
public:
void func (const ParamType& param) const
{
param.invertFunc (*this);
}
void func (const DerivedParamType2& param) const
{
std::cout << "Derived2::func (DerivedParamType2)" << std::endl;
}
};
class DerivedParamType1 : public ParamType
{
public:
void invertFunc (const Derived1& deriv) const
{
deriv.func (*this);
}
void invertFunc (const Derived2& deriv) const
{
deriv.func (*this);
}
};
class DerivedParamType2 : public ParamType
{
public:
void invertFunc (const Derived1& deriv) const
{
deriv.func (*this);
}
void invertFunc (const Derived2& deriv) const
{
deriv.func (*this);
}
};
int main (int argc, char* argv[])
{
ParamType* paramType = new DerivedParamType1;
Base* deriv = new Derived1;
deriv->func (*paramType);
return 0;
}
Please note that there are actually three jumps (departures) when you asked to Base::func(ParamType)call Derived1::func(DerivedParamType1). If you are satisfied either:
Base::func(ParamType) causes DerivedParamType1::func(Derived1)
or
ParamType::func(Base) causes Derived1::func(DerivedParamType1)
then you can eliminate one of the jumps.
source
share