C ++: Интерфейс, обеспечивающий определение copy-constr - PullRequest
6 голосов
/ 09 апреля 2011

Есть ли какой-нибудь способ для класса интерфейса реализовать определение конструктора копии и, возможно, также других конструкторов? В моем случае у меня есть IResource чистый абстрактный класс, и я хочу, чтобы все классы, реализующие этот интерфейс, определяли copy-constr, конструктор для загрузки из файла и конструктор для загрузки из памяти.

Ответы [ 4 ]

5 голосов
/ 09 апреля 2011

Чтобы построить объект, вам нужно знать конкретный класс для использования (как он иначе узнает, какой объем памяти выделить, или какую виртуальную таблицу использовать и т. Д.??).Таким образом, интерфейс не работает при работе с конструкторами, и вы не можете использовать интерфейсы (чисто виртуальные) для обеспечения существования такого конструктора.Когда вы думаете об этом, это естественно, виртуалы работают только тогда, когда у вас есть полиморфный объект, т.е. после создания экземпляра.Любой, кто ссылается на ваш интерфейс IResource, будет когда-либо иметь дело только с созданными объектами и никогда не трогает конструктор.

Вы можете навязать такие ограничения на материал, используя шаблоны, если хотите.Просто вызывая конструктор копирования из шаблонной функции, компилятор будет жаловаться, если встретит создание экземпляра шаблона с использованием типа, который не имеет конструктора копирования.

1 голос
/ 09 апреля 2011

Вы не можете применить это, и это также не будет правильным способом. Напротив, вы должны предотвратить использование открытых конструкторов копирования в полиморфной иерархии классов ...

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);
}
0 голосов
/ 09 апреля 2011

вы можете выдвинуть все требования к реализации ресурса следующим образом:

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);
    /* ... */
}
0 голосов
/ 09 апреля 2011

Что-то в вашем проекте использует абстрактный класс IResource, и почему-то я сомневаюсь, что это требует, чтобы используемые им объекты содержали определенные конструкторы.

Что-то еще создает IResource объекты (возможно много вещей) и для этого нужно использовать конструктор.Создаваемые конкретные классы должны реализовывать необходимые конструкторы, иначе код не будет компилироваться.

Поэтому ответ на ваш вопрос заключается в том, что вы принудительно используете присутствие конструкторов с помощью , используя эти конструкторы внекоторый другой код для создания объектов.Имейте в виду, что если конструкторы нигде не используются, они не нужны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...