0

我正在尝试创建一个基于其参数的专门化而重载的函数,例如:

class DrawableObject...;
class Mobile : public DrawableObject...;

class Game
{
    AddObject(DrawableObject * object)
    {
        // do something with object
    }
    AddObject(Mobile * object)
    {
        AddObject(dynamic_cast<DrawableObject *>(object));
        DoSomethingSpecificForSpecializedClass();
    }
};

...但是我的 MS 编译器给了我这个错误:

错误 C2681:“Mobile *”:dynamic_cast 的表达式类型无效

这两个类都有虚函数。在这种情况下,这是错误的演员阵容吗?我尝试过使用 C 风格的演员表,一切都按预期运行。此外,这种设计是否有任何潜在的陷阱?

4

5 回答 5

4

对于显式向上转换,请使用static_cast.

您的设计应该可以正常工作。请注意,AddObject()如果您尝试传递一个可以隐式转换为Mobile*and的对象DrawableObject*,例如指向派生自Mobile.

于 2010-01-07T21:46:02.490 回答
1

正如尼尔所说,演员阵容完全是错误的。 dynamic_cast<>用于从基础向下转换为派生,而不是相反。更好的方法是分解出常见的代码,例如:

class Game {
protected:
    void commonAddObject(DrawableObject *obj) {
        // do common stuff here
    }
public:
    void addObject(DrawableObject *obj) {
        commonAddObject(obj);
        // do DrawableObject specific stuff here
    }
    void addObject(MobileObject *obj) {
        commonAddObject(obj);
        // do MobileObject specific stuff here
    }
};

或为不依赖于类型重载的DrawableObject和创建单独的方法。MobileObject如果可以的话,我宁愿完全避开演员阵容。

于 2010-01-07T22:09:52.337 回答
0

向上转换始终是免费且安全的。这意味着您不需要使用受保护的 dynamic_cast。static_cast 将是执行此操作的正确方法,尽管 c 样式转换也可以。实际上,您应该能够取消第二个 AddObject 函数,因为如果您将指向 Mobile 对象的指针传递给 DrawableObject 函数,它将调用正确的函数而无需任何转换。除非您打算将专门的功能放在重载函数中,否则我不会编写它。

于 2010-01-07T21:57:35.827 回答
0

演员表是错误的,而且完全没有必要——Mobile 已经是一个 DrawableObject。

于 2010-01-07T21:47:53.850 回答
0

...或完全删除您的 AddObject(Mobile * object) 重载。如果没有那个函数,它将被“隐式转换”到它的基类,并且 AddObject(DrawableObject*) 函数将被调用。您无需为层次结构中的每种类型手动添加重载和强制转换。

添加了编辑代码,我想澄清一些关于您的设计的建议。

您的“游戏”类要么统一处理所有对象,要么不统一处理。如果没有,那么提供一个公开可用的通用“AddObject”重载就没有意义了——你已经与各个对象紧密耦合,所以你最好放弃它和松散耦合设计的伪装。您仍然可以将其作为私有辅助函数 AddObjectInternal。由于它不是重载,因此您不需要强制转换来消除呼叫的歧义。

如果您希望或希望统一处理所有对象,请考虑将您当前放入 AddObject 重载的此类逻辑放入对象类的虚函数中。然后,您只有一个 AddObject 方法,该方法调用所添加对象的虚函数。

于 2010-01-07T21:50:19.593 回答