我发布了一个问题,我会在发布代码后解释:
template <class T>
std::shared_ptr<T>
getWidget(const std::string& id) {
auto iter = findObject(id);
if (iter != m_widgets.end()) return std::dynamic_pointer_cast<T>(*iter);
return nullptr;
}
const Widget::Ptr
getType(const std::string& id) {
auto iter = findObject(id);
if (iter != m_widgets.end()) {
if ((*iter)->getWidgetType() == "Label")
return std::dynamic_pointer_cast<Label>(*iter);
else if ((*iter)->getWidgetType() == "Editbox")
return std::dynamic_pointer_cast<EditBox>(*iter);
else if ((*iter)->getWidgetType() == "ButtonLabel")
return std::dynamic_pointer_cast<ButtonLabel>(*iter);
else if ((*iter)->getWidgetType() == "Menu")
return std::dynamic_pointer_cast<Menu>(*iter);
}
}
auto type = SceneManager::getCurrentScene().m_gui.getType(widgetId);
SceneManager::getCurrentScene().m_gui.getWidget<decltype(type)>(widgetId)->attachToMenu(getId());
Widget::Ptr
只是typedef std::shared_ptr<Widget>
。如您所见,m_widgets
是一个填充了小部件的列表,这些小部件是Label
,EditBox
,ButtonLabel
和Menu派生自的基类。我试图向下转到这些类,以便我可以获取类型,并使用我的getWidget()
来编辑派生对象。但是我收到了这个错误:
错误:&#39; class std :: shared_ptr&#39;没有名为&#39; attachToMenu&#39; |
的成员
这显然意味着它没有正确投射并且它返回了一个Widget。任何帮助都会很棒,谢谢!
答案 0 :(得分:1)
“Widget :: Ptr只是一个typedef std :: shared_ptr。”
我认为它是std::shared_ptr<Widget>
的typedef。如果是这样,那么dynamic_pointer_cast
仅在函数体内强制转换,在它之外的类型是std::shared_ptr<Widget>
(这是因为返回类型意味着向上转换):
auto type = SceneManager::getCurrentScene().m_gui.getType(widgetId);
// type is std::shared_ptr<Widget>, that is, a pointer to base type
此外,使用getWidget<decltype(type)>
您实际上希望getWidget<T>
返回std::shared_ptr<std::shared_ptr<Widget>>
,这远远不是您想要实现的目标。
最终,向下转型通常表明设计不佳。我相信您可以通过在attachToMenu
基类中创建Widget
方法虚拟来解决问题,然后在运行时不需要RTTI。考虑一下:
class Widget
{
public:
virtual ~Widget() = default;
virtual void attachToMenu(const std::string& id) = 0;
};
class EditBox : public Widget
{
public:
virtual void attachToMenu(const std::string& id) override
{
// do the stuff
}
};
std::shared_ptr<Widget> widget = std::make_shared<EditBox>();
widget->attachToMenu(getId()); // calls EditBox::attachToMenu
答案 1 :(得分:0)
宣布
时auto type = ...
type
的类型将始终为Widget::Ptr
,因为这是函数返回的类型。所有向下投射都发生在函数内,所以无关紧要。然后,当您使用getWidget
拨打decltype(type)
时,会使用静态类型,因此再次使用Widget::Ptr
。你需要重新设计。