我对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中的数据。)

07-24 09:46
查看更多