如何将虚拟调用从未模板化的父级干净地分派到模板化的子级
how to cleanly dispatch virtual calls from non templated parent to templated child
我有一个非常丑陋的实现,我想重构它,但我不确定如何重构。这是我所拥有的:
一些模板化对象
template< typename T>
class Thing { };
接口
class IService {
public:
virtual void func(void* arg) = 0;
};
一个实现它的模板类
template< typename T>
class Service< T> : public IService {
virtual void func(void* arg) {
func((Thing< T>* )arg);
}
void func(Thing< T>* arg) {
// do something with arg
}
};
原因是我想要一个可以传递的非模板化的IService。模板化IService将导致通过大型代码库进行大规模重构。
因此,我实例化Service<T> 对象,传递IService,并使用模板化的Thing对象调用func,这会对采用实际Thing对象的类似函数进行难看的强制转换。有没有什么干净的方法可以在不模板化IService的情况下实现这一点?
编辑:更多上下文。这就是我真正想要的:
template<typename T>
class IService {
public:
virtual void func(Thing<T>* arg) = 0;
};
但是,我无法对IService进行模板化。
假设你不想或不能给Thing
一个基类,并且给定的Service<T>
只能处理具有相同T
的Thing
,你可以这样做:
class IService {
public:
template <typename T>
void func(Thing<T>* arg) {
auto self = dynamic_cast<Service<T>*>(this);
if (self) {
self->func(arg);
} else {
// decide how to handle this error
}
}
};
func
将不是虚拟的。这只是一个从IService派生的模板策略,需要有一个func(Thing<T>*)
方法。
也许Thing
的一些接口可以做到这一点?
class IThing { };
template< typename T>
class Thing: public IThing { };
class IService {
public:
virtual void func(IThing* arg) = 0;
};
template< typename T>
class Service: public IService {
virtual void func(IThing* arg) {
Thing<T> *thing = dynamic_cast<Thing<T> *>(arg);
if (thing) {
// implementation
}
}
};
我假设您希望通过使用非模板化的IService
类来键入erase Thing
的<T>
模板参数,并且在IService
的实现中不关心T
。我不确定这些假设是否正确,但这里有一个可能的解决方案。
我还假设在Thing
中调度virtual
在您的用例中就足够了。
// Create a `ThingBase` class to "type-erase" `Thing`'s
// template parameter. `ThingBase` should contain your
// `func`, as `virtual`.
struct ThingBase
{
virtual void func();
};
// Your `Thing<T>` class should override `func`
template <typename T>
struct Thing : ThingBase
{
void func() override { /* ... */ }
};
// Your `IService` now only needs to be as follows:
struct IService
{
void func(ThingBase& x)
{
x.func();
}
};
相关文章:
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 为什么 std::unique 不调用 std::sort?
- 调用专用模板时出错"no matching function for call to [...]"
- 选择要调用的构造函数
- C++为什么尽管我调用了void函数,它却不起作用
- 构造函数正在调用一个使用当前类类型的函数
- 变量没有改变?通过向量的函数调用
- 没有为自己的结构调用列表推回方法
- 调用'begin(int [n])'没有匹配函数
- 为什么在c++中调用虚函数意味着消息分派
- 在虚拟分派之后调用基成员(模拟类似虚拟析构函数的分派)
- 在虚方法中调用虚方法时,是否应该发生虚分派
- 如何将虚拟调用从未模板化的父级干净地分派到模板化的子级