C ++:实现copy-constr定义的接口

时间:2011-04-08 20:50:53

标签: c++ oop inheritance interface

接口类是否有任何方法可以强制执行复制构造函数的定义,也可能还有其他构造函数的定义?在我的例子中,我有一个IResource纯抽象类,我希望所有实现此接口的类都定义一个copy-constr,一个从文件加载的构造函数,以及一个从内存加载的构造函数。

4 个答案:

答案 0 :(得分:5)

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

如果您愿意,可以使用模板对内容强制执行这些约束。通过简单地从模板化函数调用复制构造函数,如果遇到使用没有复制构造函数的类型的模板实例化,编译器将会抱怨。

答案 1 :(得分:1)

你不能强制执行,也不是正确的方法。相反,您应该阻止在多态类层次结构中使用公共拷贝构造函数...

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);
}

答案 2 :(得分:0)

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

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

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

答案 3 :(得分:0)

您可以将所有需求推送到资源实现,如下所示:

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);
    /* ... */
}