C++和强制转换运算符

C++ and cast operators

本文关键字:转换 运算符 C++      更新时间:2023-10-16

我有一个关于c++转换运算符的问题。

假设您有一个类Message和几个子类:Message1Message 2

假设您有一个类Event和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以避免那些检查,如果你自己的检查是不合格的,我想我会被石头砸死的。)

最好的方法(在我看来)是在基类中进行适当的虚拟接口设计。您可以避免以这种方式从基础铸造到派生。

此外,如果使用vector<Event>,则可以对所有Event进行切片。您只能使用vector<Event*>来拥有派生对象的集合,因为基指针可以指向派生对象,但基对象不能包含派生数据。(矢量中所有派生的Event都将错过theMessage,并且只有包含在Event中的数据。)

通常,当您有派生类时,您应该使用虚拟函数。

在您的示例中,也许消息中的"内容"可以通过虚拟函数获得。

这个演员阵容:

    Event1 *e1 = static_cast<Event1*>(&theEvent);

不会起作用。theEventEvent1Message,这意味着无论你从中得到什么消息都将是"随机垃圾",因为你最初只有一个Event

如果你想在事件数组中存储"任何类型的事件",那么你需要存储指向Event类型的指针,否则你肯定会遇到上面的切片问题。

你的想法完全没有希望。可以按结构和向量中的值存储所有基类。这意味着它们将完全是基类类型,而不是任何派生类型。因此铸造对你没有任何帮助。

您必须了解如何在集合或结构中存储多态对象。(基本上通过某种指针,正确安排所有权问题)。

在解决了存储问题后,您可以回来进行铸造——相比之下,这将很容易。