C++ C++;instanceof/extends的等效值
我想创建一个资源管理器,我知道它应该如何工作,但我不知道如何在C中相应地设置它++C++ C++;instanceof/extends的等效值,c++,polymorphism,C++,Polymorphism,我想创建一个资源管理器,我知道它应该如何工作,但我不知道如何在C中相应地设置它++ class Resource{ public: virtual void loadFromFile(); }; class Texture: public Resource{ public: void loadFromFile(){ do texture specific loading } }; class Mesh: public Resource{ public: void lo
class Resource{
public:
virtual void loadFromFile();
};
class Texture: public Resource{
public:
void loadFromFile(){ do texture specific loading }
};
class Mesh: public Resource{
public:
void loadFromFile(){ do mesh specific loading }
};
class ResourceManager{
private:
vector<Resource*> resources;
public:
template <typename T>
void addResource(){
T* resource = new T;
resource->loadFromFile();
resources.push_back(resource);
}
};
类资源{
公众:
虚拟void loadFromFile();
};
类纹理:公共资源{
公众:
void loadFromFile(){do纹理特定加载}
};
类别:公共资源{
公众:
void loadFromFile(){do mesh specific loading}
};
班级资源经理{
私人:
媒介资源;
公众:
模板
void addResource(){
T*资源=新的T;
resource->loadFromFile();
资源。推回(资源);
}
};
如何强制执行
T
正在扩展Resource
,并且不是一个碰巧有同名方法的类?由于resources
向量具有类型Resource*
,如果尝试插入不是Resource
派生的内容,则会出现编译时错误
否则,您可以选择:
class ResourceManager{
private:
std::vector<Resource*> resources;
public:
template <typename T>
std::enable_if_t<std::is_base_of_v<Resource, T>, void> addResource(){
T* resource = new T;
resource->loadFromFile();
resources.push_back(resource);
}
}
但仅当loadFromFile
在Resource
上声明,而不是在T
中声明时(因此在您的示例中可以使用)(感谢@RemyLebeau)由于
资源
向量的类型为资源*
,如果尝试插入非资源
派生的内容,则会出现编译时错误
否则,您可以选择:
class ResourceManager{
private:
std::vector<Resource*> resources;
public:
template <typename T>
std::enable_if_t<std::is_base_of_v<Resource, T>, void> addResource(){
T* resource = new T;
resource->loadFromFile();
resources.push_back(resource);
}
}
但仅当loadFromFile
在Resource
上声明,而不是在T
中声明时(因此在您的示例中可以使用)(感谢@RemyLebeau)要获得友好的错误消息,您可能需要使用:
#包括
模板
void addResource(){
静态_断言(std::is_base_of_v,“T必须从资源派生”);
...
如果
T
不是从Resource
派生的,这将在编译时生成错误。要获得友好的错误消息,您可能需要使用:
#包括
模板
void addResource(){
静态_断言(std::is_base_of_v,“T必须从资源派生”);
...
<>这将在编译时产生错误,如果<代码> t>代码>不是从<代码>资源< /代码>派生的。您可以使用sFIEAE,您使用的是哪个版本的C++?<代码>资源。如果
T
没有从Resource
继承,则将无法编译。自C++20以来,约束和概念可能很有用。我看不出instanceof
有什么关系。Java也有同样的限制,即不能将非派生对象推入基引用(因为它不会编译,就像C++)不需要代码< > /<代码>。您可以使用sFIEAE,您使用的是哪个版本的C++?<代码>资源。如果T
没有从Resource
继承,则将无法编译。自C++20以来,约束和概念可能很有用。我看不出instanceof
有什么关系。Java也有同样的限制,即不能将非派生对象推入基引用(因为它不会编译,就像C++).Noinstanceof
需要这样做。另外,如果您将T*resource
更改为resource*resource
,那么如果new T
无法分配给resource*
@RemyLebeau如果您是对的,我将在answerresource*resource=new T();这样,如果我调用loadFromFile,它将使用派生类实现?在某个时候,我读到它因为一些奇怪的事情而无法工作。@markotath,可能是切片?这不适用于指针。@markotath您已经将该方法标记为virtual
,因此将对哪个函数进行运行时评估,该函数将是called,因此在本例中,如果您的T
使用新实现重写该方法,则将调用该函数(换句话说,将调用派生方法,而不是基类中的方法,因此它将具有您期望的行为)另外,如果您将T*resource
更改为resource*resource
,那么如果new T
无法分配给resource*
@RemyLebeau,则编译器还有另一个故障点。如果您是对的,我将在answerResoirce*resource=new T();这样,如果我调用loadFromFile,它将使用派生类实现?在某个时候,我读到它因为一些奇怪的事情而无法工作。@markotath,可能是切片?这不适用于指针。@markotath您已经将该方法标记为virtual
,因此将对哪个函数进行运行时评估,该函数将是called,因此在本例中,如果您的T
使用新实现重写该方法,则将调用该函数(换句话说,将调用派生方法,而不是基类中的方法,因此它将具有您期望的行为)
#include <type_traits>
template <typename T>
void addResource(){
static_assert (std::is_base_of_v<Resource, T>, "T must derive from Resource");
...