Search code examples
c++inheritancevoid-pointers

Specifying void* parameter in derived function


I would like to do something that probably is not possible in Cpp, but I could not find a post about this specifically.

I want to have a derived class specify the type of a void* parameter on a virtual function.

I have a base class called interface with a send function.

// pure virtual
class Interface{
    virtual bool Send(const void*)=0;

};

struct Packet{
    DataType data;
};

class SpecificInterface{
     bool Send(const DataType*);
}

Is there a way to make something like this work? The intent is that SpecificInterface::Send implements Interface::Send. Allowing SpecificInterface to not be a pure virtual while restricting the void* to a specific packet type.

Otherwise I know I could take a void* parameter and static_cast it into the Packet* type; however, I do not want others to send a pointer type that cannot be cast to Packet*.

Let me know if this is not clear


Solution

  • @RSahu is correct, of course. You could still use a virtual method to do about the same thing:

    class Interface {
        virtual bool send(const void*) = 0;
    };
    
    struct Packet {
        DataType data;
    };
    
    class SpecificInterface {
        bool send(cont void*) override { 
            send(static_cast<DataType*>(data));
        }
        bool send(cont DataType*); // code which actually does something
    };
    

    However - I recommend against your whole approach to begin with - it is massively unsafe, since the validity of the type is never checked! It's a source of many potential bugs. More often than not, you can avoid doing this. Here are a few things you might try instead:

    1. std::any - a class which doesn't offer you compile-time type safety, but at least checks types at run-time. You would have a send(const std::any& data) virtual function, and inside it you would call std::any_cast<DataType>(data) to get a DataType or std::any_cast<DataType>(&data) to get a DataType *.

    2. Probably even better - the Curiously-recurring template pattern (CRTP):

      template <typename T>
      class Interface {
           virtual bool send(T*) = 0;
      }; 
      
      class SpecificInterface : Interface<DataType> {
          bool send(cont DataType*) override;
      }