我经常遇到与SubType Polymorphism相关的问题,我正在寻找一个我可能还没有意识到的优雅解决方案。
这是一个简单的继承层次结构:
struct BaseClass {
virtual ~BaseClass() = 0;
std::string name;
};
template <T>
struct DerivedClass
{
DerivedClass(const std::string& _name): name(_name) { }
};
现在我可以创建许多具有不同名称和模板类型的DerivedClass实例,并使用它们的BaseClass将它们存储在数组中。
std::vector<BaseClass*> array;
array.push_back(new DerivedClass<TABC>("abc"));
array.push_back(new DerivedClass<TDEF>("def"));
...
这是非常标准的运行时多态性。
然而,当我有一个新的功能层是特定于类型的添加并且不希望这个新层在两个方向上耦合时,我最终不得不做这样的事情:
template <typename T>
void method(DerivedClass<T>* object) { }
void callMethod(BaseClass* object)
{
// this is the logic I'm trying to move up a layer
if (object->name == "abc") method<TABC>(object);
else if (object->name == "def") method<TDEF>(object);
}
这些方法中的每一个都必须具有与要转换的编译时类型相同的运行时字符串列表,这意味着添加新类型需要进行大量更改。
如果我假设新层只支持编译时已知的特定选项(无论如何都是这样),那么在运行时添加新类型是可行的,但是不能在这一层,没问题。
我目前的想法是,如果我要将一个虚方法引入到带有函数指针的类层次结构中,我可以根据特定的编译时类型为第二层中的每个方法注册函数指针(理想情况下只指定一次) ),有点像双调度方法。
有什么想法,建议吗?
答案 0 :(得分:3)
您需要该链接根据字符串调用特定模板版本,您可以做的最好的事情是拥有string
- &gt; lambda function
的字典,并使用该字符串作为查找来获取要拨打function<>
。这避免了嵌套的if
,并且在编译时(默认列表)和运行时(任何更改只是数组更改)都相对容易维护。
答案 1 :(得分:1)
而不是窃取Sean Parent的雷声,我将引导您进行这次演讲,这将向您展示如何干净,安全和简单地实现这一目标。
该技术称为多态性作为实现细节&#39;。它改变了我编写代码的方式。
https://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Class-of-Evil