1

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

假设你有一个类Message和几个子类:Message1 Message 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 插入到 avector<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());
    }

我有一个问题:在最后一次cast之后,我看不到Message2的实例信息(总是只有它的父类Message) 这种情况下,有必要使用dynamic_cast吗?

4

3 回答 3

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*>派生对象的集合,因为基指针可能指向派生对象,但基对象不能保存派生数据。(向量中的所有派生Events 都将丢失theMessage,并且仅包含 中的数据Event。)

于 2013-06-23T23:06:56.763 回答
3

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

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

这个演员表:

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

不管用。theEventEvent1a小Message- 这意味着你从中得到的任何消息都是“随机垃圾”,因为你一开始只有 a Event

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

于 2013-06-23T23:13:09.053 回答
1

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

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

在你解决了存储问题之后,你可以回来拿铸件——相比之下这很容易。

于 2013-06-23T23:14:40.800 回答