我已经阅读了几个关于 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;
}
};
它是我在使用 box2d 物理的游戏中用于碰撞检测的类的简化版本。我希望 box2d 的细节不会过多地分散我想要展示的内容。我有一个非常相似的类“事件”,它创建不同类型的事件处理程序,其结构相同(使用基类 EventHandler 的子类而不是 EntityContact)。