Search code examples
c++constructorinterfacevirtual

No viable conversion between Derived Class (constructor has parameters) and Base Class (constructor is absent of parameters)


I have an abstract class Handle() containing a handle() method (amongst others). This class is implemented several times, with each class handling a different kind of data (stored as bytes) in a different way, e.g.

class BaseHandle
{
   virtual void handle(uint8_t *ptr, uint8_t data_size) = 0;
}

and

class DerivedHandleA : public BaseHandle 
{
   void handle(uint8_t *ptr, uint8_t data_size)
   {
      //DO THINGS WITH DATA OF KIND "A"
   }
}


class DerivedHandleB : public BaseHandle 
{
   void handle(uint8_t *ptr, uint8_t data_size)
   {
      //DO THINGS WITH DATA OF KIND "B"
   }
}

My issue is that in handling certain kinds of data the handle() method needs access to instances of other classes to call their member functions, which I would ordinarily pass through the constructor, so currently my code is like this:

class DerivedHandleC : BaseHandle 
{
private:
   HelperClass helper;

   void handle(uint8_t *ptr, uint8_t data_size)
   {
      //DO THINGS WITH DATA OF KIND "C" WITH FUNCTIONS FROM helper
   }

public:
   DerivedHandleC(HelperClass helper) : BaseHandle() helper(helper){};
}

The issue arises because I have a std::vector containing each instance of the Handler class, which is iterated through each time I get data to find the correct handler and send on the data. This works fine with DerivedHandle without parameters, but with the constructor with parameters I receive a no viable conversion from 'DerivedHandleC' to 'BaseHandle' when pushing it to my vector, which is understandable.

My question is, what should I be doing instead of passing the parameters I need through the constructor? I would prefer not to simply add the same parameters to all derived classes where they are not needed, though I am aware this would solve my compilation error.


EDITS

Adding std::vector code on request:

Declarations

   typedef std::vector<std::unique_ptr<BaseHandler>> HandlerVec;
   HandlerVec handlers;

Push back method

registerHandler(std::unique_ptr<BaseHandler> handler)
{
   handlers.push_back(std::move(handler));
}

Examples call of pushback

registerHandler(std::make_unique<DerivedHandleA>());
registerHandler(std::make_unique<DerivedHandleC>(helper));


Solution

  • Class types declared using the class keyword have by default private inheritance, compared to class types declared with struct.

    Here's an example:

    struct A {};
    
    struct B : A {
        // inherit publicly from A, the outside world can see the inheritance graph 
    };
    
    class C : A {
        // privately inherit, the outside world cannot see the inheritance
    };
    

    To inherit publicly, use a struct or use classes with a specifier to override the default behaviour:

    class D : public A {
        // inherit publicly
    };