【问题标题】:Calling an object-specific function on a STL vector of polymorphic objects在多态对象的 STL 向量上调用特定于对象的函数
【发布时间】:2013-08-19 21:02:48
【问题描述】:

所以我有一个类层次结构,它本质上将Entity 类作为父抽象类和一堆从它派生的其他类,例如DoorPlayerGround 等。

我还有一个三维的vector,它存储了指向Entity 类型对象的指针,我用派生对象填充了这个vector。 在Door 类中,我有一个名为isOpen() 的方法,它只返回一个bool。此函数特定于 Door 类,既不在 Entity 类中,也不在它的任何其他派生中(因为我不需要检查,例如,Ground 对象是否打开) .

现在,知道在vector 位置ijk 存在一个类型为Door 的对象,我想像这样调用isOpen 方法:vector[i][j][k]->isOpen()。不幸的是,当我这样做时,编译器返回 class Entity has no member named isOpen()。这是可以理解的,因为函数 isOpen()Door 类独有的,但是我该怎么做才能使这种调用成为可能?

【问题讨论】:

  • 不要只告诉我们您的代码; 显示更多更有效率。其次,dynamic_cast<> 可能对您有用。不要只是把它扔进去,首先了解如何使用它。

标签: c++ function vector polymorphism virtual


【解决方案1】:

解决此问题的一种方法是先向下转换为Door *。但是,为了使这种向下转换是类型安全的,您应该使用dynamic_cast<Door *>()。如果Entity 还没有虚方法,可以添加虚析构函数。

class Entity {
    //...
    virtual ~Entity () {}
};

void foo (Entity *e) {
    //...
    Door *door = dynamic_cast<Door *>(e);
    if (door) {
        if (door->isOpen()) {
            //...
        }
    }
    //...
}

【讨论】:

    【解决方案2】:

    简答:

    将实体扔到一扇门上:static_cast&lt;Door*&gt;(vector[i][j][k])-&gt;isOpen()

    长答案:

    如果您需要知道特定派生类型位于特定位置,则您的设计不合适。解决这个问题可能很简单,只需将 isOpen() 函数向上移动到 Entity 并返回 true 的默认实现。或者它可能需要重新考虑与vector 的成员一起使用的代码。

    【讨论】:

    • 如果被指向的实体不是实际上是DoorDoor的派生,在层次结构的更下方,这是未定义的行为 并且肯定会崩溃。 static_cast&lt;&gt; 不是在这里使用的转换类型。请参阅其描述 in this question and answer 了解原因。
    • 您可能希望使用reinterpret_cast,而不是static_cast - 尽管该方法不是推荐的方法。长答案更符合预期 - 修复设计。
    • 啊,感谢您建议使用类型转换。在班级重新设计方面,您对我将如何去做有什么建议吗?似乎具有同一父类的多个对象的向量是我的程序不可或缺的:(
    • 带有空值检查的 dynamic_cast 是否更合适?设计听起来确实有点缺陷。不过不确定是否将 IsOpen 移至基类,因为 IsOpen 听起来并不适用于每种类型。我认为重新思考整个方法是要走的路。
    • @Kindread 更适合使用dynamic_cast&lt;&gt; 并在触发该方法之前检查它是否为NULL。你是对的。
    【解决方案3】:

    考虑使用 dynamic_cast&lt;&gt; 的语言支持的多态转换。对于引用,它将抛出异常 (std::bad_cast),但对于 指针,如果目标类型不兼容,它将简单地返回 NULL,所以...假设您的基类及其派生确实是多态的(即至少一个虚拟方法):

    Door* pDoor = dynamic_cast<Door*>(vector[i][j][k]);
    if (pDoor)
        pDoor->isOpen();
    

    保留对设计的评论。意见就像......是的。每个人都有一个。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-15
      • 2011-08-15
      相关资源
      最近更新 更多