我有3节课:
class Super
{
virtual int getType() { return 1; }
}
class Special : public class Super
{
virtual int getType() { return 2; }
}
class SpecialSpecial : public class Special
{
virtual int getType() { return 3; }
}
我有一个以std::vector<Super*>
为参数的函数:
void handleClasses( std::vector<Super*> superVector )
{
foreach element in superVector //Pseudocode!!
{
if( element->getType() == 1 )
std::cout << "Thats a SuperClass" << std::endl;
else if( element->getType() == 2 )
std::cout << "Thats a SpecialClass" << std::endl;
else if( element->getType() == 3 )
std::cout << "Thats a SpecialSpecialClass" << std::endl;
}
}
可能有一个继承自班级Special
的用户:
class ParalellSpecial : public class Special
{
virtual int getType() { return 4; }
}
现在函数handleClasses
无法理解类型为4的新类,但它应该能够使用下一个高级类(在这种情况下它是Special
)。
有人会如何实施这样的事情?是否存在允许创建类的层次顺序的设计模式,如果当前类无法使用(因为它未知),则下一个可用的超类将用作后备?
注意:类型标识符仅用于演示目的。肯定有更好的方法来识别C ++(RTTI)中的classtype。
答案 0 :(得分:2)
这里有2个可能的答案:
1)如果你认为你需要知道一个对象到底是什么类型,那么也许你的封装是错误的。也许handleClasses()应该在对象上调用一个方法,每个类应该提供不同的实现吗?
2)如果这是您真正需要知道对象类型的极少数情况之一,请使用dynamic_cast<>
。这就是它的用途。 E.g:
void handleClasses( std::vector<Super*> superVector )
{
foreach element in superVector //Pseudocode!!
{
if( dynamic_cast<SpecialSpecial *>(element) != 0 )
// SpecialSpecial or a subclass of SpecialSpecial
std::cout << "Thats a SpecialSpecialClass" << std::endl;
else if( dynamic_cast<Special *>(element) != 0 )
// Special or a subclass of Special
std::cout << "Thats a SpecialClass" << std::endl;
else
// Super or a subclass of Super
std::cout << "Thats a SuperClass" << std::endl;
}
}
答案 1 :(得分:0)
这实际上取决于你的实际问题。通常,如果您的每个类都有特殊情况,而您无法使用多态,那么继承可能不是解决您问题的好方法。
另一个想法是创建一个知道类型关系的全局类型注册表。然后,您可以使用注册表在层次结构中移动,直到找到可以处理的类型。注册表可以只是一个DAG,其中type-id为节点。
答案 2 :(得分:0)
让事情发生变化的第一个解决方案:
子类将超类的类型集成到它们自己的Type-ID中
- Super
获得Type == 1
- Special
获得Type == 21
- SpecialSpecial
获得Type == 321
- ParalellSpecial
获取Type == 421
handleClasses
现在检查第一个数字是否已知(ParalellSpecial
不是这种情况。然后检查第二个数字是否已知(情况是这样)然后打印相关数字消息(或做任何想做的事情,例如从Super
转换为Special
)
这个概念的缺点是每个层次结构级别只能有10个类。我认为,类型标识符的概念也不是最优的。
认为有更好的解决方案。