提问者:小点点

如何编写具有接受不同类型参数,从一个基抽象类继承并实现其接口的泛型函数的类?


在我的项目中,我需要有一个带接口的基本抽象类,它派生出类实现。 问题是,这些派生的类具有接受不同类型参数的泛型函数。 我使用函数模板在我的派生类中编写了这些泛型函数。

我尝试在抽象基类中执行纯抽象模板化函数,但它不起作用。

下面是一个小程序,它具有我正在尝试实现的功能,由于虚拟,它无法编译:

#include <vector>

class ObjectTransformerBaseAbstractClass {
public:
    virtual template<typename TStructure> TStructure ToStructure(std::vector<unsigned char> bytes) = 0;
    virtual template<typename TStructure> std::vector<unsigned char> ToBytes(TStructure structure) = 0;
};

class ObjectTransformer1 : public ObjectTransformerBaseAbstractClass {
    template <typename TStructure> TStructure ToStructure(std::vector<unsigned char> bytes) {
        // some implementation
    }

    template <typename TStructure> std::vector<unsigned char> ToBytes(TStructure structure) {
        // some implementation
    }
};

class ObjectTransformer2 : public ObjectTransformerBaseAbstractClass {
    template <typename TStructure> TStructure ToStructure(std::vector<unsigned char> bytes) {
        // some other implementation
    }
    template <typename TStructure>
    std::vector<unsigned char> ToBytes(TStructure structure) {
        // some other implementation
    }
};

template <typename TStructure>
void coutStructureBytes(ObjectTransformerBaseAbstractClass *objectTransformerBaseAbstractClass, TStructure structure) {
    // transform structure to bytes using the passed objectTransformerBaseAbstractClass object and cout it.
}

在我的基类中,我需要说“实现这些纯抽象的泛型函数,它们接受不同类型的不同参数,并在派生的类中做一些事情”。 在我的派生类中,我需要实现这些接受不同类型参数的纯抽象泛型函数。

我不明白如何实现我想要的这个功能(你可以在上面的程序中看到,如果它编译并工作的话)。 请推荐一个解决方案或解释如何使此工作。


共1个答案

匿名用户

您正在尝试使用声明为virtual的方法模板。 那是不可能的。 另见对一个相关问题的回答。

似乎您正在尝试创建某种序列化/反序列化机制。 您希望将不同的结构(以不同的类实现)转换为字节,并且希望能够通过以某种方式解释字节来重新创建正确类型的对象。

让我们首先处理序列化问题。 通过使用每个结构都应该实现的序列化方法为所有结构定义一个接口,您可以很容易地解决这个问题:

class Structure
{
public:
    virtual std::vector<uint8_t> ToBytes() = 0;

    // any other functionality common to all structures
};

一个特定的结构将如下所示:

class SomeStructure: public Structure
{
public:
    SomeStructure(std::vector<uint8_t> bytes)
    {
        // deserialize (create object from bytes)
    }

    std::vector<uint8_t> ToBytes() override
    {
        // serialize
    }

    // explained below
    static constexpr uint8_t TypeId()
    {
        return 42;
    }

    // any specific methods for the structure
};

现在是反序列化问题。 您需要有某种方法来标识字节流中的类类型。 假设您的结构总是将唯一的类ID作为第一个字节写入。 然后可以使用工厂,它通过识别类型来创建正确的对象:

class StructureBuilder
{
public:
    virtual Structure* FromBytes(std::vector<uint8_t> bytes) = 0;
    virtual uint8_t TypeId() = 0;
};

class StructureFactory
{
public:
    static StructureFactory& Instance()
    {
        // usual singleton stuff: create if not existing yet, then return instance
    }

    Structure* FromBytes(std::vector<uint8_t> bytes)
    {
        for (auto& builder : builders)
        {
            if (builder->TypeId() == bytes[0])
                return builder->BuildStructureFromBytes(bytes);
                
            return nullptr;
        }
    }

    void Add(StructureBuilder* builder)
    {
        // add to list
    }

    void Remove(StructureBuilder* builder)
    {
        // remove from list
    }

private:
    StructureFactory()
    {
    }
    std::list<StructureBuilder*> builders;
    static StructureFactory* instance;
};

所有的构建器看起来都非常相似,因此您可以在这里使用一个模板,以便为每个结构创建一个模板:

template <typename T>
class TypedStructureBuilder: public StructureBuilder
{
public:
    TypedStructureBuilder()
    {
        StructureFactory::Instance().Add(this);
    }

    virtual ~TypedStructureBuilder()
    {
        StructureFactory::Instance().Remove(this);
    }

    Structure* BuildStructureFromBytes(std::vector<uint8_t> bytes) override
    {
        return new T(bytes);
    }

    uint8_t TypeId() override
    {
        return T::TypeId();
    }
};

然后,要在工厂注册一些新结构,您需要做的就是将其放在某个地方(我会将其放在sometructure.cpp):

static TypedStructureBuilder<SomeStructure> builder;

希望这能帮上忙。