Dou*_*Dan 8 c++ oop dynamic-cast
我已经阅读了几个关于C++动态转换的线程,所有人都声称它表明设计不好.在其他语言中,我在检查对象的类型时从未考虑过太多.我从不使用它作为多态性的替代,只有当强耦合看起来完全可以接受时.我经常遇到的这些情况之一:有一个列表(我在C++中使用std :: vector)的对象,都是从一个公共基类派生的.该列表由一个允许知道不同子类的对象管理(通常它是管理对象类中私有类的一个小层次).通过将它们保存在单个列表(数组,向量,...)中,我仍然可以从多态中受益,但是当一个操作意图作用于特定子类的对象时,我使用动态转换或类似的东西.
如果没有我缺少的动态强制转换或类型检查,是否存在针对此类问题的不同方法?我真的好奇那些不惜一切代价避免这些的程序员会如何处理它们.
如果我的描述过于抽象,我可以在C++中编写一个简单的例子(编辑:见下文).
class EntityContacts {
private:
class EntityContact {
private:
virtual void someVirtualFunction() { }; // Only there to make dynamic_cast work
public:
b2Contact* m_contactData;
};
class InternalEntityContact : public EntityContact {
public:
InternalEntityContact(b2Fixture* fixture1, b2Fixture* fixture2){
m_internalFixture1 = fixture1;
m_internalFixture2 = fixture2;
};
b2Fixture* m_internalFixture1;
b2Fixture* m_internalFixture2;
};
class ExternalEntityContact : public EntityContact {
public:
ExternalEntityContact(b2Fixture* internalFixture, b2Fixture* externalFixture){
m_internalFixture = internalFixture;
m_externalFixture = externalFixture;
};
b2Fixture* m_internalFixture;
b2Fixture* m_externalFixture;
};
PhysicsEntity* m_entity;
std::vector<EntityContact*> m_contacts;
public:
EntityContacts(PhysicsEntity* entity)
{
m_entity = entity;
}
void addContact(b2Contact* contactData)
{
// Create object for internal or external contact
EntityContact* newContact;
if (m_entity->isExternalContact(contactData)) {
b2Fixture* iFixture;
b2Fixture* eFixture;
m_entity->getContactInExFixtures(contactData, iFixture, eFixture);
newContact = new ExternalEntityContact(iFixture, eFixture);
}
else
newContact = new InternalEntityContact(contactData->GetFixtureA(), contactData->GetFixtureB());
// Add object to vector
m_contacts.push_back(newContact);
};
int getExternalEntityContactCount(PhysicsEntity* entity)
{
// Return number of external contacts with the entity
int result = 0;
for (int i = 0; i < m_contacts.size(); ++i) {
ExternalEntityContact* externalContact = dynamic_cast<ExternalEntityContact*>(m_contacts[i]);
if (externalContact != NULL && getFixtureEntity(externalContact->m_externalFixture) == entity)
result++;
}
return result;
}
};
Run Code Online (Sandbox Code Playgroud)
它是一个类的简化版本,用于在使用box2d物理的游戏中进行碰撞检测.我希望box2d的细节不会分散我想要展示的内容.我有一个非常相似的类'Event',它创建不同类型的事件处理程序,它们以相同的方式构造(使用基类EventHandler的子类而不是EntityContact).
至少从我的角度来看,dynamic_cast存在是有原因的,有时候使用它是合理的.这可能是其中之一.
鉴于您描述的情况,一种可能的替代方法可能是在基类中定义您需要的更多操作,但如果您为基类或其他不支持这些操作的类调用它们(可能是静默地),则将它们定义为失败操作.
真正的问题是以这种方式定义您的操作是否有意义.回到典型的基于动物的层次结构,如果你正在与鸟类合作,那么Bird类定义一个fly成员通常是明智的,对于少数无法飞行的鸟类来说,只是让它失败(理论上应该重命名)像这样的东西attempt_to_fly,但很少完成很多).
如果你看到很多这样的东西,它往往表明你的课程缺乏抽象 - 例如,你可能真的想要一个成员,而不是一个fly或者attempt_to_fly,travel这取决于个体动物来确定是否要做游泳,爬行,散步,飞行等
这
但是当一个操作要作用于特定子类的对象时,我使用动态强制转换或类似的东西
听起来对象建模不正确。您有一个包含子类实例的列表,但它们并不是真正的子类,因为您不能以相同的方式对它们进行操作(Liskov 等)。
一个可能的解决方案是扩展基类,以便拥有一组某些子类可以重写的无操作方法。但这听起来仍然不太正确。
| 归档时间: |
|
| 查看次数: |
1078 次 |
| 最近记录: |