Compile error: "no matching function for call to" when returning static_cast reference

Compile error: "no matching function for call to" when returning static_cast reference

我在这个模板化方法上有这个编译错误 no matching function for call to ‘Color::Color(Component&)’ :

template<typename U>
inline U& getObject(const std::string& key)
  {
    return (static_cast<U>(*(_map.at(key))));
  }

我这样称呼它(组件是我的类型,包含我的地图):

components.getObject<Color>("Color").getColor();

Color 继承自 Component_map 是一个字符串和 Component* (组件上的指针)。

我有很多从 Component 派生的类型,我在我的映射中存储了一个指向它们的指针。但是当我尝试从映射中获取一个组件并将其转换为特定类型以使用它时,我得到了上面的编译错误。我不明白为什么。

I have a lot of types derivating from Component and I store a pointer to them in my map. But when I try to get a Component from the map and cast it to a specific type to use it, I get the compile error above. I don't understand why.

因为你的函数编码错误。

您的函数正在从映射中检索 Component* 指针,取消引用该指针以访问对象的 Component 部分(不是完整的派生类型),然后尝试构造派生 class 的 临时 实例,其中 Component 作为输入。

换句话说,您的示例本质上是这样做的:

inline Color& getObject(const std::string& key)
{
    TComponent *pcomp = _map.at(key);
    Color tmp(*pcomp); // <-- error here
    return tmp;
}

该错误意味着您的 Color class 没有接受 Component 作为输入的构造函数,因此无法编译。

即使代码确实编译了,它仍然是错误的,因为你返回一个 reference 给一个临时对象,该对象在函数退出时被销毁,所以调用者将最终得到对无效内存的悬空引用。

正如@MikeVine 在评论中所述,您可以编写这样的函数来修复它:

template<typename U>
inline U& getObject(const std::string& key)
{
    return static_cast<U&>(*(_map.at(key)));
}

这会起作用,因为它消除了临时对象的构造,并且 returns 对存储在地图中的现有对象的引用。

您也可以这样编写函数:

template <typename U>
inline U& getObject(const std::string& key)
{
    return *(static_cast<U*>(_map.at(key)));
}

此代码首先将 Component* 指针转换为 U* 指针,然后取消引用它以访问派生的 class 对象。

如果您在运行时不确定请求的组件是否真的是请求的类型,您可以添加一些额外的错误处理以在返回它之前进行确认:

template <typename U>
inline U& getObject(const std::string& key)
{
    U *ptr = dynamic_cast<U*>(_map.at(key));
    if (!ptr) throw std::invalid_argument("");
    return *ptr;
}

或者:

template<typename U>
inline U& getObject(const std::string& key)
{
    return dynamic_cast<U&>(*(_map.at(key)));
}