Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/152.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++_Templates_Instantiation - Fatal编程技术网

C++ 所有派生类的显式实例化

C++ 所有派生类的显式实例化,c++,templates,instantiation,C++,Templates,Instantiation,我有一个组件类: class Component { } 然后是继承自碰撞器的碰撞器类: class Collider :public Component { } 以及从碰撞器继承的球体碰撞器: class SphereCollider :public Collider { } 最后是一个GameObject类,您可以使用它添加或删除组件 GameObject.h标题: 除非我还添加以下内容,否则不会编译: template Collider &GameObject::Ge

我有一个
组件
类:

class Component 
{

}
然后是继承自碰撞器的
碰撞器
类:

class Collider :public Component
{

}
以及从碰撞器继承的
球体碰撞器

class SphereCollider :public Collider
{

}
最后是一个
GameObject
类,您可以使用它添加或删除组件

GameObject.h标题:

除非我还添加以下内容,否则不会编译:

template Collider &GameObject::GetComponent<Collider>();
template Collider &GameObject::AddComponent<Collider>();
模板碰撞器&GameObject::GetComponent();
模板碰撞器&GameObject::AddComponent();
在GameObject.cpp源文件中

由于使用
GetComponent
AddComponent
函数的所有内容都继承自
Component
类,因此是否有方法自动为继承自
Component
类的每个类进行显式实例化

我尝试了
模板组件&GameObject::GetComponent()
模板组件&GameObject::AddComponent()但这不起作用,只给了我“未解析的外部符号”错误

目前我唯一的选择是将所有模板函数放在头文件中,但这将为
GetComponent
AddComponent
模板函数公开一个重要的代码

不,不可能

1)
template Component&GameObject::GetComponent()
仅是具体的
组件
类的显式实例化。编译器找不到纯虚拟方法的定义,所以会出现链接器错误

2) 如果不添加相应的include,则从
组件派生的某些类在GameObject.cpp中可能无法访问。因此,在一般情况下,编译器甚至理论上也无法获得所有继承者的列表,因为这些信息仅在链接时可用

由于使用
GetComponent
AddComponent
函数的所有内容都继承自
Component
类,因此是否有方法自动为继承自
Component
类的每个类进行显式实例化

简单的回答是“不”

组件
派生类正好实现了这一点。您得到的是一个派生类——除此之外什么都没有。如果基类具有在派生类中重写的
virtual
成员函数,则可以在派生类中实现该行为

任何额外的东西都必须编码。需要编写的额外代码的数量取决于额外的功能和您提供的框架

这里有一个可能的方法来实现你的目标。请注意,这使用了
动态\u cast
,如果不小心,可能会失败

class Component 
{
   public:
      virtual ~Component() {}
};

#include <map>

// Implement GameObject with no knowledge of any of the classes derived 
// from Component. That will be one sure fire way of making sure that it can
// be used for any class derived from Component.

class GameObject
{
   public:

    //Add functionality
    template <class T>
    T& AddComponent()
    {
       T* obj = new T{};
       AddComponent(getTypeID<T>(), obj);
       return *obj;
    }

    //Get functionality
    template <typename T>
    T& GetComponent()
    {
       T* obj = dynamic_cast<T*>(GetComponent(getTypeID<T>()));
       return *obj;
    }

   private:

    // If necessary, the implementation can be moved to a .cpp file.
    void AddComponent(int typeID, Component* obj)
    {
       components[typeID] = obj;
    }

    // If necessary, the implementation can be moved to a .cpp file.
    Component* GetComponent(int typeID)
    {
       return components[typeID];
    }

    // Key function.
    // It gets a unique integer for every type.
    template <class T>
       static int getTypeID()
       {
          static int typeID = getNextID();
          return typeID;
       }

    // If necessary, the implementation can be moved to a .cpp file.
    static int getNextID()
    {
       static int nextID = 0;
       return ++nextID;
    }

    std::map<int, Component*> components;
};

class Collider : public Component
{
};

class SphereCollider :public Collider
{
};

int main()
{
   GameObject go;
   go.AddComponent<Collider>();
   go.AddComponent<SphereCollider>();

   Collider c = go.GetComponent<Collider>();
   SphereCollider sc = go.GetComponent<SphereCollider>();
}
类组件
{
公众:
虚拟~Component(){}
};
#包括
//在不了解任何派生类的情况下实现GameObject
//来自组件。这将是确保它能够
//可用于从组件派生的任何类。
类游戏对象
{
公众:
//添加功能
样板
T&AddComponent()
{
T*obj=新的T{};
AddComponent(getTypeID(),obj);
返回*obj;
}
//获取功能
样板
T&GetComponent()
{
T*obj=dynamic_cast(GetComponent(getTypeID());
返回*obj;
}
私人:
//如有必要,可以将实现移动到.cpp文件中。
void AddComponent(int-typeID,Component*obj)
{
组件[typeID]=obj;
}
//如有必要,可以将实现移动到.cpp文件中。
组件*GetComponent(int类型ID)
{
返回组件[typeID];
}
//关键功能。
//它为每种类型获取一个唯一的整数。
样板
静态int getTypeID()
{
静态int-typeID=getNextID();
返回typeID;
}
//如有必要,可以将实现移动到.cpp文件中。
静态int getNextID()
{
静态int nextID=0;
return++nextID;
}
地图组件;
};
类碰撞器:公共组件
{
};
类球对撞机:公共对撞机
{
};
int main()
{
游戏对象围棋;
go.AddComponent();
go.AddComponent();
碰撞器c=go.GetComponent();
SphereCollider sc=go.GetComponent();
}

get
@NeilButterworth我之所以需要使用模板,是因为我需要使用模板,因为我正在寻找一种特殊的语法,比如
gameObject.AddComponent()<代码>就像C++,但是C++。我认为没有其他方法可以在没有模板的情况下获得语法。@StoryTeller说得对。我只希望那些使用统一但程序C++的人能够使用它或者将他们的代码移植到C++中。@程序员然后No。你基本上想生成一个没有源代码的函数模板的新实例。您要么需要提供用户将需要的模板的任何实例,要么需要为他们的编译器提供源代码以完成缺少的实例。我已经有了
T&AddComponent()
T&GetComponent()
函数通过
dynamic_cast
和一种机制实现,该机制确保两个函数都不能返回
null
,因为这两个函数都返回引用。我只是在寻找一种方法来隐藏其中的长代码。我讨厌不接受和接受另一个答案,但你的答案是我要找的。它有一个变通方法,我可以使用
AddComponent(int-typeID,Component*obj)
隐藏长代码。Thanks@Programmer,很高兴听到我能帮忙。
GameObject gameObject;
SphereCollider sCollider1 = gameObject.AddComponent<SphereCollider>();
SphereCollider sCollider2 = gameObject.GetComponent<SphereCollider>();
Component sCollider3 = gameObject.GetComponent<Component>();
Collider sCollider = gameObject.GetComponent<InnoEngine::Collider>();
template Collider &GameObject::GetComponent<Collider>();
template Collider &GameObject::AddComponent<Collider>();
class Component 
{
   public:
      virtual ~Component() {}
};

#include <map>

// Implement GameObject with no knowledge of any of the classes derived 
// from Component. That will be one sure fire way of making sure that it can
// be used for any class derived from Component.

class GameObject
{
   public:

    //Add functionality
    template <class T>
    T& AddComponent()
    {
       T* obj = new T{};
       AddComponent(getTypeID<T>(), obj);
       return *obj;
    }

    //Get functionality
    template <typename T>
    T& GetComponent()
    {
       T* obj = dynamic_cast<T*>(GetComponent(getTypeID<T>()));
       return *obj;
    }

   private:

    // If necessary, the implementation can be moved to a .cpp file.
    void AddComponent(int typeID, Component* obj)
    {
       components[typeID] = obj;
    }

    // If necessary, the implementation can be moved to a .cpp file.
    Component* GetComponent(int typeID)
    {
       return components[typeID];
    }

    // Key function.
    // It gets a unique integer for every type.
    template <class T>
       static int getTypeID()
       {
          static int typeID = getNextID();
          return typeID;
       }

    // If necessary, the implementation can be moved to a .cpp file.
    static int getNextID()
    {
       static int nextID = 0;
       return ++nextID;
    }

    std::map<int, Component*> components;
};

class Collider : public Component
{
};

class SphereCollider :public Collider
{
};

int main()
{
   GameObject go;
   go.AddComponent<Collider>();
   go.AddComponent<SphereCollider>();

   Collider c = go.GetComponent<Collider>();
   SphereCollider sc = go.GetComponent<SphereCollider>();
}