我对c++强制转换运算符有疑问。
假设您有一个Message
类和几个子类:Message1
Message 2
等。
假设您有一个Event
类以及Event的不同子类:Event 1
Event 2
在这两种情况下,我都可以从ID
(例如field)中区分出子类的类型。
class Message {
....
int MessageID;
}
class Message1 : public Message {
//other fields;
}
class Message2 : public Message {
//other fields;
}
class Event {
int eventID;
}
class Event1 {
Message theMessage;
Message getMessage();
}
class Event2 {
Message theMessage;
}
我将实例Event1或Event2插入
vector<Event>
在这种情况下,当我由运营商提取事件时,尽管我确定您有Event1的实例,但是使用static_cast
是正确的吗?例如: Event theEvent = myVector.at(i);
Event1 *e1 = static_cast<Event1*>(&theEvent);
if(e1->getID() == xxx) {
Message2 *m2 = static_cast<Message2*>(&e1->getMessage());
}
我有一个问题:在最后一次转换之后,我看不到实例信息为Message2(始终仅是其父类Message的实例)
在这种情况下,有必要使用dynamic_cast吗?
最佳答案
e1->getMessage()
返回消息类型的对象,而不是指针。因此,您的数据将被 slice 。另外,您在此处投射了一个指向临时对象的指针:
Message2 *m2 = static_cast<Message2*>(&e1->getMessage());
如果返回指针,则可以执行此操作。
Message * getMessage() { return &theMessage; }
static_cast
是将基本指针转换为派生指针的正确方法,而无需任何运行时检查。 当然,“安全”的方法是使用dynamic_cast运算符,因为它将在将派生对象转换为基本指针或引用时执行运行时检查。 (如果我告诉您坚持使用static_cast
以避免如果您自己进行防故障检查,那我将在这里死定了;))最好的方法(我认为)是在基类中进行适当的虚拟接口(interface)设计。您可以避免以这种方式从基础转换为派生。
另外,如果您使用
Event
,则对所有vector<Event>
进行 slice 。您只能使用vector<Event*>
来获取派生对象的集合,因为基本指针可能指向派生对象,但基本对象无法保存派生数据。 ( vector 中所有派生的Event
都将丢失theMessage
,而只包含Event
中的数据。)