C++ C++;instanceof/extends的等效值

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

我想创建一个资源管理器,我知道它应该如何工作,但我不知道如何在C中相应地设置它++

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++).No
instanceof
需要这样做。另外,如果您将
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");
    ...