C ++: design, function template override and no polymorphism

They have a base class A and a derived class B that overrides the Func functional pattern:

class A
{
          A() {...};
          ~A() {};

          template <class T>
          void Func(const String &sInput, T &tResult)
          {...}
};

class B : public A
{
          B() {...}
          ~B() {};

          template <class T>
          void Func(const String &sInput, T &tResult)
          {...}
};

      

(Note that Func is not virtual given the lack of support in C ++ for templated virtual functions.)

Now you have API mainprog, class M:

class M
{
  M(boost::shared_ptr<A> &pInterfaceInput): pInterface(pInterfaceInput)
  {}  

  template <class T>
  Evaluate(const String &sInput, T &tResult) 
  {
    pInterface->Func<T>(sInput, tResult);
  }

  private:
  const boost::shared_ptr<A> pInterface;
};

      

I want the Evaluate function here to support function calls in base class A or any of its derived classes (such as B). This class was written with polymorphism in mind before I reworked classes A and B to have templated functions.

Now the problem is that if I pass a generic base type pointer to a derived type, then the base class Func will be called, not the derived class it points to.

How do I get around the lack of dynamic polymorphism? I considered creating a class template class M for a generic pointer type and having a static_cast in the constructor to ensure that the type is of the base class (A) or derived class type.

What's the best way to do this? I would prefer not to change classes A and B to get around this issue, but all suggestions are appreciated.

Thank.

+2


source to share


2 answers


Sounds like a double dispatch problem . Perhaps this would be a good place to implement the pattern

For example, create a class Evaluator

and for each T

subclass ConcreteEvaluator<T>

. Give methods A

and B

who attend Evaluator

. Something like:

class Evaluator 
{
    virtual void visit_A(A* object);
    virtual void visit_B(B* object);
};

template <typename T>
class ConcreteEvaluator : public Evaluator
{
    public:
    String* input_reference;
    T& result_reference;

    ConcreteEvaluator(String& input_reference_,T& result_reference_) :
        input_reference(input_reference_), 
        result_reference(result_reference_) {}

    virtual void visit_A(A* object) {
        object->Func(input_reference,result_reference);
    }
    virtual void visit_B(B* object) {
        object->Func(input_reference,result_reference);
    }
 }

class A
{
...
virtual void apply_evaluator(Evaluator *eval) {eval->visit_A(this);}
...
}

class B
{
...
virtual void apply_evaluator(Evaluator *eval) {eval->visit_B(this);}
...
}

      



For each subclass A

to ConcreteEvaluator

have to be added to the new method, so this method works best if the class hierarchy A

is stable. And for each subclass, A

it must have a specific function apply_evaluator

.

On the other hand, it can be a complete excess. For about the same amount of work, you can always just pay the price to upgrade M::Evaluate

:

class M
{
    ...
    void Evaluate(const String& sInput, T& tResult)
    {
        // try to downcast to each subclass of A.  Be sure to check
        // sub-subclasses first
        try
        {
            dynamic_cast<B*>(pInterface.get())->Func(sInput, tResult);
            return;
        }
        catch (std::bad_cast& ) { }
        ...
        // nothing worked.  It must really be an A
        pInterface->Func(sInput,tResult);
    }
    ...
};

      

+3


source


I am showing in the question Templatized Virtual function how to use type erasure to get some of the effects of a virtual member function. Depending on what you want to do in Func (), you can use the same technique here.



+1


source







All Articles