代码之家  ›  专栏  ›  技术社区  ›  Izzo

可以在指向不同模板类实例的指针之间强制转换吗?

  •  0
  • Izzo  · 技术社区  · 7 年前

    假设我有一个名为 Pool 一个抽象类 PoolObject

    类模板 允许用户创建包含特定类型池对象的池。例如:

    template<class T, size_t pool_size>
    Pool()
    {
        // assert that type T is derived from PoolObject
    
        public:
            int grab(){};
            void release(int object_id){};
    
        private:
            std::array<T, pool_size> pool_members_;
    }
    

    现在假设我想创建几个不同的池来管理几个不同的对象类型。

    class PoolObject1 : public PoolObject{};
    class PoolObject2 : public PoolObject{};
    class PoolObject3 : public PoolObject{};
    class PoolObject4 : public PoolObject{};
    
    Pool<PoolObject1, 100> pool_1;
    Pool<PoolObject2, 100> pool_2;
    Pool<PoolObject3, 100> pool_3;
    Pool<PoolObject4, 100> pool_4;
    

    现在假设我想创建一个用于获取池对象的工厂函数,以及一个用于释放池对象的销毁函数。一个简单的实现将使用switch语句来确定应该使用哪个池。

    int factory(int object_type)
    {
        switch(object_type)
        {
            case 1:
            return pool_1.grab();
    
            case 2:
            return pool_2.grab();
    
            case 3:
            return pool_3.grab();
    
            case 4:
            return pool_4.grab();
    
        }
    }
    

    虽然很简单,但对于在这些池上操作的任何方法,我都必须实现相同的case语句。例如,销毁方法。

    void destroy(int object_type, int object_id)
    {
        switch(object_type)
        {
            case 1:
            return pool_1.release(object_id);
    
            case 2:
            return pool_2.release(object_id);
    
            case 3:
            return pool_3.release(object_id);
    
            case 4:
            return pool_4.release(object_id);
        }
    }
    

    随着定义了更多的对象类型,switch语句将不断增长,这将使管理和更新每个方法变得困难。

    一个更简单的解决方案是使用查找表来获取相关池,然后调用适当的方法。

    例如,我可以尝试存储指向数组中每个池的指针。

    std::array<void*, 4> pool_ptrs =
    {
        &pool_1,
        &pool_2,
        &pool_3,
        &pool_4
    };
    

    通过拥有这个池指针数组,我现在可以重写工厂并销毁方法,如下所示:

    int factory(int object_type)
    {
        return static_cast<Pool*>(pool_ptrs[object_id])->grab();
    }
    
    void destroy(int object_type, int object_id)
    {
        return static_cast<Pool*>(pool_ptrs[object_id])->destroy(object_id);
    }
    

    但是,此代码不会编译。编译器抱怨 Pool* 缺少模板参数。

    所以我理解为什么我的代码不能编译,但是,我不知道什么是合适的解决方案。我基本上想使用类模板作为“抽象类”。我不想给 Pool<Object1, 100> 或指向 Pool<Object2, 100> ,我只想给

    所以我的问题是:可以在指向不同模板类实例的指针之间进行强制转换吗?

    1 回复  |  直到 7 年前
        1
  •  2
  •   MSalters    7 年前

    答案很简单:

    是的,您可以转换指针,不同的实例共享一个公共的基类。就像普通类型一样。您需要添加 PoolBase . 请注意,这不是模板,而是常见的非模板接口。

    不,你不能 PoolBase::get(int object_type) 返回一个 PoolObject1 , PoolObject2 PoolObject3 取决于运行时条件 object_type . 返回类型在编译时确定。