您可以在指向不同模板 class 实例的指针之间进行转换吗?
Can you cast between pointers that point to different template class instances?
假设我有一个名为 Pool
的容器 class 模板和一个名为 PoolObject
的抽象 class
class 模板 Pool
允许用户创建包含特定类型池对象的池。例如:
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 语句。比如destroy方法。
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 语句也会越来越多,这会导致管理和更新每个方法变得很痛苦。
一个更简单的解决方案是查找 table 以获取有问题的池,然后调用适当的方法。
例如,我可以尝试将指向每个池的指针存储在一个数组中。
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*
缺少模板参数。
所以我明白为什么我的代码无法编译,但是,我不知道合适的解决方案是什么。我基本上想将 class 模板用作 "abstract class"。我不想将指针转换为 Pool<Object1, 100>
或指向 Pool<Object2, 100>
的指针,我只想将指针转换为 Pool
所以我的问题是:您可以在指向不同模板 class 实例的指针之间进行转换吗?
答案很简单:
是的,您可以转换指针,不同的实例共享一个公共基class。就像普通类型一样。您需要添加 PoolBase
。请注意,这不是模板,它是常见的非模板界面。
不,你不能有 PoolBase::get(int object_type)
其中 returns 有 PoolObject1
、PoolObject2
或 PoolObject3
,具体取决于运行时条件 object_type
。 Return 类型在编译时确定。
假设我有一个名为 Pool
的容器 class 模板和一个名为 PoolObject
class 模板 Pool
允许用户创建包含特定类型池对象的池。例如:
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 语句。比如destroy方法。
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 语句也会越来越多,这会导致管理和更新每个方法变得很痛苦。
一个更简单的解决方案是查找 table 以获取有问题的池,然后调用适当的方法。
例如,我可以尝试将指向每个池的指针存储在一个数组中。
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*
缺少模板参数。
所以我明白为什么我的代码无法编译,但是,我不知道合适的解决方案是什么。我基本上想将 class 模板用作 "abstract class"。我不想将指针转换为 Pool<Object1, 100>
或指向 Pool<Object2, 100>
的指针,我只想将指针转换为 Pool
所以我的问题是:您可以在指向不同模板 class 实例的指针之间进行转换吗?
答案很简单:
是的,您可以转换指针,不同的实例共享一个公共基class。就像普通类型一样。您需要添加 PoolBase
。请注意,这不是模板,它是常见的非模板界面。
不,你不能有 PoolBase::get(int object_type)
其中 returns 有 PoolObject1
、PoolObject2
或 PoolObject3
,具体取决于运行时条件 object_type
。 Return 类型在编译时确定。