c++:接口强制copy-constr定义

C++: Interface enforcing definition of copy-constr

本文关键字:copy-constr 定义 接口 c++      更新时间:2023-10-16

接口类是否有办法强制定义复制构造函数和其他构造函数?在我的例子中,我有一个IResource纯抽象类,我希望实现这个接口的所有类都定义一个复制构造函数,一个用于从文件加载的构造函数,以及一个用于从内存加载的构造函数。

为了构造一个对象,您需要知道要使用的具体类(否则它如何知道要分配多少内存,或者使用哪个虚拟表,等等?)因此,在处理构造函数时,接口不起作用,并且不能使用接口(纯虚函数)来强制存在这样的构造函数。当你想到它时,这是很自然的,虚拟只有在你有一个多态对象时才能工作,即在实例化之后。任何引用你的IResource接口的人都只会处理实例化的对象,而永远不会触及构造函数。

如果你想的话,你可以使用模板来强制这些约束。通过简单地从模板化函数中调用复制构造函数,如果遇到使用没有复制构造函数的类型的模板实例化,编译器将会报错。

你不能强制执行,这也不是一个正确的方法。相反,应该防止在多态类层次结构中使用公共复制构造函数…

struct IResource {
    virtual IResource* Clone() const = 0;
    virtual ~IResource() {}
};

IResource的实现者应该遵循以下模式:

class ConcreteResource : public IResource, public boost::noncopyable { // or equivalent
public:
    virtual ConcreteResource* Clone() const;
    explicit ConcreteResource(std::string const & pString) : mString(pString) {}
private:
    std::string mString;
};
ConcreteResource* ConcreteResource::Clone() const {
    return new ConcreteResource(this->mString);
}

在您的项目中使用IResource抽象类,不知怎的,我怀疑它要求它使用的对象包含特定的构造函数。

其他创建 IResource对象(可能很多东西),并且必须使用构造函数。创建的具体类必须实现必要的构造函数,否则代码将无法编译。

所以你的问题的答案是,你通过在其他代码中使用这些构造函数来创建对象来强制构造函数的存在。请记住,如果构造函数没有在任何地方使用,则它们是不必要的。

您可以像这样将所有需求推送到资源实现中:

class t_resource_interface {
protected:
    virtual ~t_resource_interface();
public:
    virtual t_serialization* serializeResource() = 0;
    virtual t_thing* cloneResource() = 0;
};
/* type disambiguators */
typedef enum t_load_from_url { LoadFromURL = 0 } t_load_from_url;
typedef enum t_load_from_memory { LoadFromMemory = 0 } t_load_from_memory;
typedef enum t_copy_constructor { CopyConstructor = 0 } t_copy_constructor;
template < typename TResourceImplementation >
class t_resource : public t_resource_interface {
public:
/* copy ctor should generally be avoided due to the expense. introduce a parameter for those cases where it's really needed and disable the standard copy ctor */
    t_resource(const t_copy_constructor& copyCtor, const t_resource& other) : t_resource_interface(), d_implementation(TResourceImplementation::CopyConstructor(other.d_implementation)) {
        MONUnusedParameter(copyCtor);
    }
    t_resource(const t_load_from_url& fromFile, const t_url& url) : t_resource_interface(), d_implementation(TResourceImplementation::LoadFromURL(url)) {
        MONUnusedParameter(fromFile);
    }
    t_resource(const t_load_from_memory& fromMemory, const t_serialization& serialization) : t_resource_interface(), d_implementation(TResourceImplementation::LoadFromMemory(serialization)) {
        MONUnusedParameter(fromMemory);
    }
    virtual ~t_resource() {
    }
public:
/* t_resource_interface requirements. implementation forwarded to TResourceImplementation */
    virtual t_serialization* serializeResource() {
        return this->d_implementation->serializeResource();
    }
    virtual t_thing* cloneResource() {
        return this->d_implementation->cloneResource();
    }
private:
/* assuming you will end up needing dynamic allocation/polymorphism along the way... */
    t_auto_pointer<TResourceImplementation> d_implementation;
private:
/* prohibited */
    t_resource(const t_resource&);
    t_resource& operator=(const t_resource&);
};
class t_image_resource_implementation : public t_resource_interface {
private:
    static t_image_resource_implementation* ValidationCheck(const t_image_resource_implementation* const arg) {
        assert(arg && "allocation or argument error");
        if (0 == arg) {
            return 0;
        }
        else if (0 == arg->isValid()) {
            delete res;
            return 0;
        }
        else {
            return arg;
        }
    }
public:
    static t_image_resource_implementation* CopyConstructor(const t_image_resource_implementation* const other) {
        return ValidationCheck(new t_image_resource_implementation(other, ...));
    }
    static t_image_resource_implementation* LoadFromURL(const t_url& url) {
    /* assuming t_image_at_url_resource_implementation exists */
        return ValidationCheck(new t_image_at_url_resource_implementation(url, ...));
    }
    static t_image_resource_implementation* LoadFromMemory(const t_serialization& serialization) {
        assert(serialization);
        if (0 == serialization) {
            return 0;
        }
        else {
            return ValidationCheck(new t_image_resource_implementation(serialization, ...));
        }
    }
/* some physical ctors and the rest of the implementation... */
public:
/* t_resource_interface requirements */
    virtual t_serialization* serializeResource() {
        return this->createSerialization();
    }
    virtual t_thing* cloneResource() {
        return this->clone();
    }
};
typedef t_resource<t_image_resource_implementation> t_image_resource;
t_error_code ConvertImageToGrayscale(const t_url& sourceUrl, const t_url& destinationUrl) {
    t_image_resource imageResource(LoadFromURL, sourceUrl);
    /* ... */
}