All derived-classes 的显式实例化
Explicit instantiation for All derived-classes
我有一个 Component
class:
class Component
{
}
然后继承自它的Collider
class:
class Collider :public Component
{
}
还有一个 SphereCollider
继承自 Collider
:
class SphereCollider :public Collider
{
}
最后,一个 GameObject
class,您可以使用它添加或删除组件。
GameObject.hheader:
class GameObject
{
//Add functionality
template <class T>
T& AddComponent();
//Get functionality
template <typename T>
T& GetComponent();
}
GameObject.cpp来源:
template <typename T>
T& GameObject::AddComponent(){}
template <typename T>
T& GameObject::GetComponent(){}
//Explicit instantiation
template Component &GameObject::GetComponent<Component>();
template Component &GameObject::AddComponent<Component>();
template SphereCollider &GameObject::GetComponent<SphereCollider>();
template SphereCollider &GameObject::AddComponent<SphereCollider>();
一切正常。我可以在没有指针的情况下从 GameObject 添加或获取组件,如下所示:
GameObject gameObject;
SphereCollider sCollider1 = gameObject.AddComponent<SphereCollider>();
SphereCollider sCollider2 = gameObject.GetComponent<SphereCollider>();
Component sCollider3 = gameObject.GetComponent<Component>();
问题:
我需要将其用作库并隐藏源文件。由于我在 GameObject.cpp 源代码中为 Component
和 SphereCollider
classes 添加了显式实例化,因此只有那些可以编译。
例如,
Collider sCollider = gameObject.GetComponent<InnoEngine::Collider>();
将无法编译,除非我还添加:
template Collider &GameObject::GetComponent<Collider>();
template Collider &GameObject::AddComponent<Collider>();
在 GameObject.cpp 来源中。
由于所有使用GetComponent
和AddComponent
函数的东西都继承自Component
class,有没有办法自动进行显式实例化对于从 Component
class?
继承的每个 class
我试过了template Component &GameObject::GetComponent<Component>();
和 template Component &GameObject::AddComponent<Component>();
但这没有用,只给了我 "unresolved external symbol" 错误。
目前我唯一的选择是将所有模板函数放在 header 文件中,但这将公开 GetComponent
和 AddComponent
模板函数的重要代码.
不,这不可能。
1) template Component &GameObject::GetComponent<Component>()
是仅针对具体 Component
class 的显式实例化。编译器找不到纯虚拟方法的定义,因此您会收到链接器错误。
2) 如果您不添加相应的包含,某些从 Component
派生的 class 可能无法在 GameObject.cpp 中访问。所以在一般情况下,编译器甚至在理论上也无法获得所有继承者的列表,因为此信息仅在链接时可用。
Since everything that uses the GetComponent
and AddComponent
functions inherits from the Component
class, is there a way to automatically make Explicit instantiation for every class that inherits from the Component
class?
简短的回答是 "No"。
从 Component
派生出 class 就可以做到这一点。您得到一个派生的 class —— 仅此而已。如果基 class 具有 virtual
成员函数,这些成员函数在派生 class 中被覆盖,您将获得在派生 class.
中实现的行为
任何额外的东西都必须编码。需要编写的额外代码量取决于额外功能和您提供的框架。
这是实现您的目标的一种可能方法。请注意这里使用了dynamic_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
class:
class Component
{
}
然后继承自它的Collider
class:
class Collider :public Component
{
}
还有一个 SphereCollider
继承自 Collider
:
class SphereCollider :public Collider
{
}
最后,一个 GameObject
class,您可以使用它添加或删除组件。
GameObject.hheader:
class GameObject
{
//Add functionality
template <class T>
T& AddComponent();
//Get functionality
template <typename T>
T& GetComponent();
}
GameObject.cpp来源:
template <typename T>
T& GameObject::AddComponent(){}
template <typename T>
T& GameObject::GetComponent(){}
//Explicit instantiation
template Component &GameObject::GetComponent<Component>();
template Component &GameObject::AddComponent<Component>();
template SphereCollider &GameObject::GetComponent<SphereCollider>();
template SphereCollider &GameObject::AddComponent<SphereCollider>();
一切正常。我可以在没有指针的情况下从 GameObject 添加或获取组件,如下所示:
GameObject gameObject;
SphereCollider sCollider1 = gameObject.AddComponent<SphereCollider>();
SphereCollider sCollider2 = gameObject.GetComponent<SphereCollider>();
Component sCollider3 = gameObject.GetComponent<Component>();
问题:
我需要将其用作库并隐藏源文件。由于我在 GameObject.cpp 源代码中为 Component
和 SphereCollider
classes 添加了显式实例化,因此只有那些可以编译。
例如,
Collider sCollider = gameObject.GetComponent<InnoEngine::Collider>();
将无法编译,除非我还添加:
template Collider &GameObject::GetComponent<Collider>();
template Collider &GameObject::AddComponent<Collider>();
在 GameObject.cpp 来源中。
由于所有使用GetComponent
和AddComponent
函数的东西都继承自Component
class,有没有办法自动进行显式实例化对于从 Component
class?
我试过了template Component &GameObject::GetComponent<Component>();
和 template Component &GameObject::AddComponent<Component>();
但这没有用,只给了我 "unresolved external symbol" 错误。
目前我唯一的选择是将所有模板函数放在 header 文件中,但这将公开 GetComponent
和 AddComponent
模板函数的重要代码.
不,这不可能。
1) template Component &GameObject::GetComponent<Component>()
是仅针对具体 Component
class 的显式实例化。编译器找不到纯虚拟方法的定义,因此您会收到链接器错误。
2) 如果您不添加相应的包含,某些从 Component
派生的 class 可能无法在 GameObject.cpp 中访问。所以在一般情况下,编译器甚至在理论上也无法获得所有继承者的列表,因为此信息仅在链接时可用。
Since everything that uses the
GetComponent
andAddComponent
functions inherits from theComponent
class, is there a way to automatically make Explicit instantiation for every class that inherits from theComponent
class?
简短的回答是 "No"。
从 Component
派生出 class 就可以做到这一点。您得到一个派生的 class —— 仅此而已。如果基 class 具有 virtual
成员函数,这些成员函数在派生 class 中被覆盖,您将获得在派生 class.
任何额外的东西都必须编码。需要编写的额外代码量取决于额外功能和您提供的框架。
这是实现您的目标的一种可能方法。请注意这里使用了dynamic_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>();
}