我有一个关于 C++ 转换运算符的问题。
假设你有一个类 Message
和几个子类:Message1
Message 2
等等
假设你有一个类 Event
以及事件的不同子类:Event 1
Event 2
在这两种情况下,我都可以将子类的类型与 ID
区分开来(如字段)
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()
返回 Message 类型的对象,而不是指针。所以你的数据将被切片。此外,您在此处转换了一个指向临时对象的指针:
Message2 *m2 = static_cast<Message2*>(&e1->getMessage());
如果你返回一个指针,你就可以做到这一点。
Message * getMessage() { return &theMessage; }
static_cast
是将基指针转换为派生指针的正确方法无需任何运行时检查。“更安全”的方法当然是使用 dynamic_cast 运算符,因为它将在转换时执行运行时检查派生到基指针或引用。 (我想如果我告诉你坚持使用 static_cast
以避免那些检查,如果你有自己的防故障检查,我想我会被石头砸死。;))
最好的方法(在我看来)是在基类中进行适当的虚拟接口(interface)设计。您可以避免以这种方式从 base 转换为 derived。
此外,您将所有 Event
切片如果你使用 vector<Event>
.您只能使用 vector<Event*>
拥有派生对象的集合,因为 Base 指针可能指向派生对象,但 Base 对象不能保存派生数据。 ( vector 中所有派生的 Event
都将丢失 theMessage
并且只有 Event
中包含的数据。)
关于C++ 和转换运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17266114/