Шаблонный класс, расширяющийся от не шаблонного базового класса и переопределяющих параметры функции - PullRequest
0 голосов
/ 08 ноября 2018

Я пытаюсь создать не шаблонный базовый класс для PacketDecoder, чтобы я мог хранить Base * в std :: map. Функция декодирования корректно переопределяется. Функция кодирования выдаёт мне эту ошибку: «кодирование не является виртуальным и не может быть объявлено чистым». Я мог бы думать об этой проблеме неправильно, исходя из фона Java. Есть ли более идиоматический подход с ++ к этой проблеме?

class Base {
public:
    virtual Packet* decode(folly::io::Cursor& cursor) = 0;
    virtual void encode(Packet* packet) = 0;
};

template<typename T, typename std::enable_if<std::is_base_of<Packet, T>::value>::type* = nullptr>
class PacketDecoder : public Base {
public:
    virtual T* decode(folly::io::Cursor& cursor) = 0;
    virtual void encode(T *packet) = 0;
};

Пример использования:

class TestDecoder : public PacketDecoder<ProxyJoinPacket> {
public:
    ProxyJoinPacket *decode(folly::io::Cursor &cursor) override {
        uint32_t stringLength;
        if (!cursor.tryReadBE<uint32_t>(stringLength)) {
            throw std::runtime_error("Failed to read string length");
        }

        if (cursor.length() < stringLength) {
            throw std::runtime_error("Too few bytes for string");
        }

        auto uuid = cursor.readFixedString(stringLength);
        return new ProxyJoinPacket(uuid);
    }

    void encode(ProxyJoinPacket *packet) override {

    }


};

std::vector<Base*> decoders;
void a() {
    decoders.insert(new TestDecoder()); // error "Allocating an object of abstract class type 'TestDecoder'"
}

1 Ответ

0 голосов
/ 08 ноября 2018

Проблема в том, что ваш исходный класс имеет эту виртуальную функцию:

virtual void encode(Packet* packet) = 0;

Тогда ваш унаследованный класс имеет следующее:

virtual void encode(T *packet) = 0;

Это две разные виртуальные функции.

Итак, когда вы делаете:

void encode(ProxyJoinPacket *packet) override {

Вы переопределяете метод только в том случае, если он унаследовал класс, а не в Base, который все еще отсутствует.

Поэтому измените свой унаследованный класс, чтобы использоватьPacket

virtual void encode(Packet* packet) = 0;

Вы также можете изменить свой унаследованный класс и добавить что-то вроде:

void encode(Packet* packet) final {
    encode(dynamic_cast<T*> packet);
}

Не забывайте и о виртуальных деструкторах ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...