Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在c+中编写get组件方法+;使用模板_C++_Templates_Components - Fatal编程技术网

C++ 在c+中编写get组件方法+;使用模板

C++ 在c+中编写get组件方法+;使用模板,c++,templates,components,C++,Templates,Components,我正在尝试编写一个统一风格的get组件方法。这是到目前为止我的代码。它会编译,但会返回找到的第一个组件,而不是正确的组件。我想我用的静态施法是错误的。有什么更好的方法可以做到这一点?注意,我不想硬编码组件类型,我希望能够编译这个引擎并使用从组件继承的任何东西来使用这个系统。还要注意,每个组件都需要作为自身返回,而不是组件*,因为这将隐藏子功能 compStruct.components是组件*s的向量 template <typename CompType> inline CompT

我正在尝试编写一个统一风格的get组件方法。这是到目前为止我的代码。它会编译,但会返回找到的第一个组件,而不是正确的组件。我想我用的静态施法是错误的。有什么更好的方法可以做到这一点?注意,我不想硬编码组件类型,我希望能够编译这个引擎并使用从组件继承的任何东西来使用这个系统。还要注意,每个组件都需要作为自身返回,而不是组件*,因为这将隐藏子功能

compStruct.components是组件*s的向量

template <typename CompType>
inline CompType getComponent()
{
    for(Component * currComp : compStruct.components)
    {
        if (static_cast<CompType>(currComp)!= nullptr)
        {
            return static_cast<CompType>(currComp);
        }
    }
    return nullptr;
}
以及组件基类:

#pragma once
class GameObject;

class Component
{
public:
    Component(GameObject * h) { host = h; }
    virtual ~Component() {}

    GameObject* getHost() { return host; }

protected:
    GameObject * host = nullptr;
};

static\u cast
绝对不是您想要的:它是静态的(编译时),因此无法确定任何运行时信息

您需要的是
dynamic\u cast
。请注意,这有几个要求,所有这些都由您的代码来满足:

  • 这些类必须是多态的。因为
    组件
    有一个虚拟析构函数
  • 必须在强制转换点定义(而不仅仅是声明)类。这也包括在内,因为
    getComponent
    是一个模板,而强制转换中的类型取决于它的模板参数(实际上是一个)。因此,定义只需要在模板实例化的地方可见(即调用
    getComponent
    的地方)。由于您大概是在进行浇筑以访问混凝土构件的构件,因此必须使其定义可见,这样一切都很好

关于
静态\u cast
有一些基本的误解:它只会执行强制转换,您有责任确保强制转换的指针实际指向目标类型的对象
static_cast
仅当源指针本身已存在时才会返回空指针,但不会返回类型不匹配

class B { /*...*/ };
class D1 : public B { };
class D2 : public B { };

D1 d1;
B* b = &d1;
D2* d2 = static_cast<D2*>(b);
它允许调用函数,如
getComponent()
,而不是
getComponent()
,此外,它还允许在函数体中使用指针,这更清楚,请参见下面我的经过适当调整的代码

那么您实际需要的是一个
动态\u cast
(根据我的个人喜好稍微调整您的代码…):


您可能需要
dynamic\u cast
,但前提是
组件是多态的。你能提供一个可以肯定的例子吗?动态强制转换需要包含这个类,我敢肯定,在这种情况下这是行不通的,因为我希望能够使用任何组件类型(我想也是这样吧?)。我将包括MCV的例子现在无论如何:)你们需要投到指针,若你们想收到这样一个
static_cast
不会返回空指针,除非所转换的指针已经是它自己了……因为我们谈论的是函数模板,所以在实例化模板时(即调用函数时)定义类就足够了。我很肯定你会在使用它的代码中涵盖它。Dynamic Cast修复了它。非常感谢。谢谢你,伙计。我没有选择Angew在评论中把它放在第一位,但你的解释肯定提高了我的理解。关于你对指针的注意:没有什么可以阻止OP将星号保留在外面,并将函数调用为
getComponent
@Aconcagua@WillHain,我认为
类型索引
基于
无序映射
是正确的比基于
dynamic_cast
的解决方案快得多,因为基于
dynamic_cast
的解决方案线性检查组件向量。另外,
dynamic\u cast
解决方案可能会失败,如果我们组件的派生层次结构超过2,比如
Component->AnimationComponent->AdvancedAnimationComponent
,并且
AdvancedAnimationComponent
被添加到
AnimationComponent
之前的向量中,然后,
getComponent
将错误地给出
AdvancedAnimationComponent
@NishantSingh另一方面,如果我们查找
AnimationComponent
,类型索引可能会有问题,但只有
AdvancedAnimationComponent
驻留在映射中。嗯,我们可以为两个索引(AC和AAC)添加AAC对象来解决(或者只为AC索引添加AAC对象,如果我们想隐藏它)。@ WillHain只应该选择几个最快的发布答案,如果所有这些都是等价的,否则,你应该选择一个你认为回答你的问题最好的。好吧,我不要求我这样做。在这种情况下,Angew列出的(涵盖的)先决条件也很好,所以你的选择很好,只是要记住未来…@WillHain如果你希望有很多实体和/或组件,并在普通操作中进行大量查找,那么在性能/可伸缩性方面要小心。有更多的性能方法可以根据需要构建ECS,但很难给出一个简单的答案。
class B { /*...*/ };
class D1 : public B { };
class D2 : public B { };

D1 d1;
B* b = &d1;
D2* d2 = static_cast<D2*>(b);
template <typename CompType>
inline CompType* getComponent();
//             ^
CompType* result = nullptr; // pointer: see above!
for(Component * currComp : compStruct.components)
{
    result = dynamic_cast<CompType*>(currComp);
    if(result)
        break;
}
return result;
auto i = map.find(std::type_index(typeid(CompType));
return i == map.end() ? nullptr : static_cast<CompType*>(i->second);
// now, you CAN use static cast, as the map lookup provided you the
// necessary guarantee that the type of the pointee is correct!