将基类的对象转换为派生类
Converting objects of base class to derived class
几天前我问了一些关于继承的澄清,这是一个我仍然试图理解的概念。这是一个后续问题,因为我仍然面临问题。
在我的项目中,我有2种类型的对象,Hand和Face,都继承自基类BodyPart。BodyPart是这样的:
class BodyPart
{
public:
typedef boost::shared_ptr<BodyPart> BodyPartPtr;
BodyPart();
virtual ~BodyPart();
private:
int commonMember1;
double commonMember2;
public:
int commonMethod1();
int CommonMethod2();
}
while Hand是这样的
class Hand : public BodyPart
{
public:
Hand();
~Hand();
private:
int numFingers;
double otherVar;
public:
int getNumFingers();
void printInfo();
}
我也有一个BodyPart元素向量
std::vector<BodyPart::BodyPartPtr> cBodyParts;
由手或头对象组成。在前面的问题中,我被告知这种方法是有意义的,我只需要使用boost static_pointer_cast
现在,现在的问题是,对于向量中的一些对象,我不知道它们是Hand
还是Head
,所以在我的代码中的某个点,我可以在cBodyParts
中有一些Hand
元素,一些Head
元素以及一些BodyPart
元素。经过进一步的分析,我能够正确地将后者分类为Hand
或Head
,并相应地修改向量中的元素,但我不知道如何制作它。我是否应该删除case类元素并创建一个具有相同属性的派生元素?在这种情况下,我应该避免继承吗?
提前感谢您的帮助
编辑:我已经增加了这些例子,使它们更清晰。
依赖强制类型转换通常是糟糕设计的标志。强制类型转换有它的位置,但看起来不是这样。
你需要问自己,你想用cBodyParts
中存储的对象做什么。当然,您将使用Hand
或Head
做不同的事情,但您可能可以以某种方式抽象它们:这就是虚函数所做的。因此,除了已经为类编写的内容之外,您只需要在其中添加一个虚函数:
class BodyPart
{
// Same as you wrote, plus:
public:
virtual void InitialisePart() = 0; // Pure virtual: each body part must say how to process itself
virtual void CalibrateJoints() {} // Override it only if the body part includes joints
}
class Head : public BodyPart
{
// Same as you wrote, plus:
public:
virtual void InitialisePart() {
// Code to initialise a Head
}
// Since a Head has no joints, we don't override the CalibrateJoints() method
}
class Hand : public BodyPart
{
// Same as you wrote, plus:
public:
virtual void InitialisePart() {
// Code to initialise a Hand
}
virtual void CalibrateJoints() {
// Code to calibrate the knuckles in the hand
}
}
然后你就不再需要任何类型转换了。例如:
for (BodyPart::BodyPartPtr part : cBodyParts) {
part->InitialisePart();
part->CalibrateJoints(); // This will do nothing for Heads
}
如您所见,根本没有强制类型转换,一切都将正常工作。该方案是可扩展的;如果您以后决定需要从BodyPart
继承额外的类,只需编写它们,您的旧代码将正常工作:
class Torso : public BodyPart
{
public:
virtual void InitialisePart() {
// Code to initialise a Torso
}
// The Torso has no joints, so no override here for CalibrateJoints()
// Add everything else the class needs
}
class Leg : public BodyPart
{
public:
virtual void InitialisePart() {
// Code to initialise a Leg
}
virtual void CalibrateJoints() {
// Code to calibrate the knee
}
// Add everything else the class needs
}
现在您不需要更改之前编写的代码:上面的for
循环将与它找到的Torso
或Leg
一起正常工作,而不需要更新
髋骨与大腿骨相连…
我想如果你有一些身体部位的合成物,也许是Body
类。
你希望正文做什么?
- 渲染本身
- 连载
- 输出其体积,或边界框,或其他度量
- 根据输入 重新定位
- 响应逆运动学物理模型
这个名单可能还会继续下去。如果您确切地知道您想要Body
做什么,您可以将该函数放在BodyPart
基类中,并让Body
遍历所有连接的主体部分的复合层次结构,例如调用render
。
另一种选择是使用Visitor
,这是一种有效地向静态继承层次结构动态添加方法的方法。
正如Kerrek SB指出的那样,这根本不可行,但为了回答实际问题,dynamic_cast
是您正在寻找的。
使用虚函数,它们将大大简化你的问题。
Else,您可以添加一些方法来区分不同的类型。但是,只在不能用其他方法时使用,即不能通过虚函数来使用。
示例1:
// in BodyPart; to be reimplemented in derived classes
virtual bool isHand() const { return false; }
virtual bool isHead() const { return false; }
// in Hand (similar to what will be in Head)
bool isHand() const { return true; }
// How to use:
BodyPart::pointer ptr = humanBodyVector[42]; // one item from the array
if(ptr->isHand())
processHand(/*cast to hand*/)
else if(ptr->isHead())
// ...
示例2:让派生类处理强制类型转换
// in BodyPart; to be reimplemented in derived classes
virtual Hand* toHand() const { return 0; }
virtual Head* toHead() const { return 0; }
// in Hand (similar to what will be in Head)
Hand* toHand() const { return this; }
- 存储模板类型以强制转换回派生<T>
- 在 C++ 中将对象转换为派生类型
- 从基类实例调用派生类方法而不进行强制转换
- 从基指针到派生的强制转换问题
- C++将派生类转换为基类时'object slicing'期间发生的情况
- 派生类(构造函数具有参数)和基类(构造函数缺少参数)之间没有可行的转换
- C ++基础私有方法在将自身转换为派生类后可以访问吗?
- 调用不在基类中的派生类函数而不进行动态强制转换,以最大程度地提高性能
- 在将派生类指针类型转换为派生类指针后,从基类指针调用派生类函数
- 我们可以在不知道其真实类型的情况下将基类指针转换为派生类指针吗?
- 为什么从基转换为派生提供此功能?
- 将基本实例指针强制转换为派生实例指针是否合法?(实例不是派生实例)
- 从从该抽象类派生的 Python 对象强制转换C++抽象类C++
- 基类到派生类的强制转换向量
- 有没有办法复制派生类指针的向量而不将其强制转换为基类?
- 为什么此代码不将基类强制转换为 c++ 中的派生类?
- 如何在运行时将指向派生类的 void* 正确转换为指向基类的 void*
- 从基类的共享指针向下转换到派生类的引用
- 为了访问方法,从基类动态转换为派生类
- 如何将矢量<派生*>转换为矢量<Base*时避免复制>