基于 C++ 专业化的重载
我正在尝试创建一个根据其参数的专门化而重载的函数,例如:
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 风格的强制转换,一切都按预期运行。另外,这个设计有没有潜在的陷阱?
I'm trying to create a function which is overloaded based on the specialization of its parameter, such as this:
class DrawableObject...;
class Mobile : public DrawableObject...;
class Game
{
AddObject(DrawableObject * object)
{
// do something with object
}
AddObject(Mobile * object)
{
AddObject(dynamic_cast<DrawableObject *>(object));
DoSomethingSpecificForSpecializedClass();
}
};
...but my MS compiler is giving me this error:
error C2681: 'Mobile *' : invalid expression type for dynamic_cast
Both classes have virtual functions. Is this the wrong cast for up-casting in this situation? I have tried with a C-style cast and everything functions as intended. Also, are there any potential pit-falls with this design?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
对于显式向上转换,请使用
static_cast
。你的设计应该可以正常工作。请注意,如果您尝试传递可隐式转换为
Mobile*
和DrawableObject*
AddObject() 的调用将不明确>,例如指向从Mobile
派生的类的指针。For explicit upcasting, use
static_cast
.Your design should work fine. Be aware that calls to
AddObject()
will be ambiguous if you try to pass an object that can be implicitly converted to bothMobile*
andDrawableObject*
, such as a pointer to a class derived fromMobile
.正如尼尔所说,演员阵容根本就是错误的。
dynamic_cast<>
用于从基类向派生类向下转型,而不是相反。更好的方法是分解出公共代码,例如:或者为
DrawableObject
和MobileObject
创建不依赖于类型重载的单独方法。如果可以的话,我宁愿完全避开选角。As Neil stated, the cast is simply wrong.
dynamic_cast<>
is for downcasting from base towards derived not the other way around. A better approach is to factor out the common code like:or to create separate methods for
DrawableObject
andMobileObject
that do not rely on overloading by types. I prefer to steer clear of casting altogether if I can.转换是错误的,并且完全没有必要 - Mobile 已经是一个 DrawableObject。
The cast is wrong, and completely unecessary - Mobile already is a DrawableObject.
升级始终是免费且安全的。这意味着您不需要使用受保护的dynamic_cast。 static_cast 是执行此操作的正确方法,尽管 c 风格的强制转换也可以工作。实际上,您应该能够取消第二个 AddObject 函数,因为如果您将指向 Mobile 对象的指针传递到 DrawableObject 函数中,它将调用正确的函数,而不需要任何转换。除非您计划在重载函数中添加专门的功能,否则我不会编写它。
Upcasting is always free and safe. That means you don't need to use a protected dynamic_cast. A static_cast would be the proper way to do this, although a c-style cast will work as well. In reality you should be able to do away with the second AddObject function because if you passed a pointer to a Mobile object into the DrawableObject function it would call the proper function without needing any casting. Unless you are planning on putting specialized functionality in the overloaded function I wouldn't write it.
...或完全删除您的 AddObject(Mobile * object) 重载。如果没有该函数,它将“隐式转换”为其基类,并且将调用 AddObject(DrawableObject*) 函数。您无需为层次结构中的每种类型手动添加重载和强制转换。
编辑代码已添加,我想澄清一些关于您的设计的建议。
您的“Game”类要么统一处理所有对象,要么不统一处理。如果没有,那么提供一个公开可用的通用“AddObject”重载是没有意义的——您已经与各个对象紧密耦合,因此您不妨放弃它和松散耦合设计的伪装。您仍然可以将其作为私有辅助函数 AddObjectInternal。由于它不是重载,因此您不需要强制转换来消除调用的歧义。
如果您想要或希望统一对待所有对象,请考虑将当前将 AddObject 重载放入对象类的虚拟函数中的逻辑放入其中。然后,您只有一个 AddObject 方法,该方法调用添加的对象上的虚函数。
...or remove your AddObject(Mobile * object) overload entirely. Without that function there, it will be "implicitly casted" to it's base class, and the AddObject(DrawableObject*) function would have been called. There is no need for you to manually add an overload and a cast for each type in your hierarchy.
Edit Code was added, I want to clarify some suggestions about your design.
Either your "Game" class treats all objects uniformly, or it does not. If it does not, there is no point in providing a generic "AddObject" overload that is publicly available - you're already coupled tightly to the individual objects, so you might as well drop it and the charade of a loosely coupled design.. You could still have it as a private helper function, AddObjectInternal. Since it's not an overload, you won't need the cast to disambiguate the call.
If you are or hope to treat all objects uniformly, consider putting such logic that you're currently putting in the AddObject overloads into virtual functions on the object class. Then, you only have one AddObject method, which calls the virtual functions on the object added.