Как реализовать два класса для автоматического принятия решения по глубокой и мелкой копии?

У меня есть следующая проблема дизайна:
у меня есть Resource с двумя видами аксессуаров:

  • один, чтобы изменить его (давайте назовем это Access)
  • один для const-подобного доступа (давайте назовем это Const_access), но вы могли бы сказать c1 = c2, и тогда c1 получит доступ к c2.

При условии Resource Я должен добиться следующего механизма копирования:

Access->Access:             deep copy
Access->Const_access:       deep copy
Const_access->Access:       deep copy
Const_access->Const_access: shallow copy

Я стремлюсь написать Access чтобы Const_access сможет использовать именно const функции в Access,
Моя текущая реализация имеет недостатки, используя:

class Access {
public:
Access(const Access&); // deep copy
void method(const Access&);
void const_method() const;
protected:
Resource res;
};
class Const_access : public Access{
private:
void method(); // only declaration
public:
Const_access(const Const_accesss&); // shallow copy
explicit Const_access(const Access&); // deep copy
};

но здесь Const_access ca; ca.Access::method() все еще работает, и я должен вручную скрыть неконстантные методы доступа. Я пробовал защищенное или частное наследование, но это запрещает гибкость для Access& обрабатывать Const_Access& тоже.

Каково было бы правильное решение этой проблемы?

0

Решение

То, что вы говорите, противоречиво.

С одной стороны, вы хотите запретить такие вещи, как:

Const_access foo;
foo.modify();

но с другой стороны, вы хотите разрешить такие вещи, как:

void bar(Access& a) {
a.modify();
}

Const_access foo;
bar(foo);

Это не имеет смысла.

Более логичные отношения — перевернуть структуру наследования:

class Const_access {
public:
Const_access(const Const_access&); // shallow copy
void const_method() const;
protected:
Resource res; // or perhaps a reference-counted pointer?
};

class Access: public Const_access {
public:
Access(const Access&); // deep copy
explicit Access(const Const_access&); // deep copy
void method();
};

Единственное, что он не дает, это глубокая копия при преобразовании Access к Const_access,

2

Другие решения

Ваша функция method() имеет публичную видимость в базовом классе, но приватно в производном классе. Это нарушает принцип подстановки Лискова. Производный класс должен расширять, а не сокращать базовый класс.

Решение состоит в том, чтобы не нарушать этот принцип. Например, сделать наследство в class Const_access частный или защищенный, или обеспечить реализацию method() в class Const_access,

0

Эта проблема может быть просто решена с помощью так называемой ленивая оценка:
создание частного клона ресурсов класса только тогда, когда функция-член хочет его изменить. Доступ к ресурсам с правами на чтение и чтение доступен с помощью частного наследования.

Таким образом, LSP соблюдается: Obj теперь безупречно публично унаследовал от Const_objпри необходимости вообще.
Есть ссылка для полного ответа.

0
По вопросам рекламы [email protected]