C ++和强制转换运算符

时间:2013-06-23 23:02:24

标签: c++ casting polymorphism static-cast

我对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?

3 个答案:

答案 0 :(得分:3)

e1->getMessage()返回Message类型的对象,而不是指针。所以你的数据将被切片。此外,您在此处投射指向临时的指针:

Message2 *m2 = static_cast<Message2*>(&e1->getMessage());

如果返回指针,则可以执行此操作。

Message * getMessage() { return &theMessage; }

static_cast是将基指针强制转换为派生指针的正确方法,无需任何运行时检查。这样做的“更安全”的方法是使用dynamic_cast运算符,因为它会在将派生的内容转换为基指针或引用时执行运行时检查。 (我想如果我告诉你坚持static_cast以避免那些检查,如果你有自己的那种证明是防止故障的话,那么我将在这里被石头打死。))

最好的方式(在我看来)是基类中适当的虚拟接口设计。您可以避免从基础转换为以这种方式派生。

此外,如果您使用Event,则会对所有vector<Event>进行切片。您只能使用vector<Event*>来获取派生对象的集合,因为Base指针可能指向派生对象,但Base对象无法保存派生数据。 (您的向量中的所有派生Event将会遗漏theMessage,并且只有Event中包含的数据。)

答案 1 :(得分:3)

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

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

这个演员:

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

不起作用。 theEventEvent1Message - 这意味着您从中获取的任何消息都将是“随机垃圾”,因为您只有Event第一名。

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

答案 2 :(得分:1)

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

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

解决了存储问题之后,您可以回来查看存储问题 - 比较容易。

相关问题