Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 905
Czarking Avatar asked Aug 28 '26 01:08

Czarking


2 Answers

When you want to override a virtual function, the number of arguments and the types of the arguments must exactly match the declaration in the base class. You'll have to use:

class SpecificInterface{
     bool Send(const void* ptr)
     {
        cont DataType* dataTypePtr = static_cast<const DataType*>(ptr);
        // Now use dataTypePtr any way you wish
     }
};

Please note that use of such code is dangerous. If ptr does not really point to a DataType object, your program will have undefined behavior.

like image 65
R Sahu Avatar answered Aug 29 '26 15:08

R Sahu


@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;
    }
    
like image 29
einpoklum Avatar answered Aug 29 '26 15:08

einpoklum