Указание параметра void * в производной функции - PullRequest
2 голосов
/ 14 июля 2020

Я хотел бы сделать что-то, что, вероятно, невозможно в Cpp, но я не смог найти сообщение об этом конкретно.

Я хочу, чтобы производный класс указывал тип void * параметр виртуальной функции.

У меня есть базовый класс interface с функцией отправки.

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

};

struct Packet{
    DataType data;
};

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

Есть ли способ заставить что-то подобное работать? Смысл в том, что SpecificInterface :: Send реализует Interface :: Send. Разрешение SpecificInterface не быть чисто виртуальным при ограничении void * конкретным c типом пакета.

В противном случае я знаю, что могу взять параметр void * и static_cast его в тип Packet *; однако я не хочу, чтобы другие отправляли тип указателя, который не может быть преобразован в Packet *.

Сообщите мне, если это не ясно

Ответы [ 2 ]

5 голосов
/ 14 июля 2020

Если вы хотите переопределить функцию virtual, количество аргументов и типы аргументов должны точно соответствовать объявлению в базовом классе. Вам нужно будет использовать:

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

Обратите внимание, что использование такого кода опасно. Если ptr на самом деле не указывает на объект DataType, ваша программа будет иметь неопределенное поведение.

4 голосов
/ 14 июля 2020

@ RSаху конечно прав. Вы все равно можете использовать виртуальный метод, чтобы сделать то же самое:

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
};

Однако - я рекомендую против для начала - это в значительной степени небезопасно, так как действительность тип никогда не проверяется! Это источник множества потенциальных ошибок. Чаще всего этого можно избежать. Вот несколько вещей, которые вы можете попробовать вместо этого:

  1. std::any - класс, который не предлагает вам безопасность типов во время компиляции, но, по крайней мере, проверяет типы во время выполнения. У вас будет виртуальная функция send(const std::any& data), и внутри нее вы должны вызвать std::any_cast<DataType>(data), чтобы получить DataType, или std::any_cast<DataType>(&data), чтобы получить DataType *.

  2. Возможно, даже лучше - Любопытно повторяющийся шаблон шаблона (CRTP):

    template <typename T>
    class Interface {
         virtual bool send(T*) = 0;
    }; 
    
    class SpecificInterface : Interface<DataType> {
        bool send(cont DataType*) override;
    }
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...