Метод клонирования с не виртуальным интерфейсом и некоторыми закрытыми переменными

У меня есть абстрактный класс сказать Figure и некоторые производные классы: Circle, Square

Фигура класса реализует:

private:
virtual double varea()=0;
double multiplier;
public:
virtual Figure * clone()=0;
double area() { return varea()*multiplier; }

Фигуры, например Площадь, ведут себя так:

private:
double L;
public:
virtual Figure * clone() {return new Square(*this);}
virtual double varea() {return L*L;}

У меня возникают трудности с назначением множителя переменной при вызове метода clone. Каков наилучший способ достичь этого? Конечно, это просто глупый пример с рядом обходных путей, но в действительности, с несколькими уровнями деривации, они не так очевидны, поэтому, пожалуйста, придерживайтесь этого паттерна.


Должен ли я пойти на виртуальный интерфейс также для метода клона? Таким образом, я могу назначить множитель непосредственно в классе Figure без необходимости сообщать каждой фигуре свой множитель.

2

Решение

Если вы не объявляете конструктор копирования для своего класса на безвозмездной основе, и это публично. Вам не нужен этот бесплатный конструктор публичных копий. Это приведет к нарезке. Создайте свой конструктор копирования для защищенного класса Figure. Ваш конструктор копии для неабстрактных производных классов должен вызывать этот конструктор защищенной копии. При этом функция-член клона так же проста, как new DerivedClass (*this):

class Figure {
private:
virtual double varea()=0;
double multiplier;
protected:
Figure () : multiplier(1.0) {}
Figure (const Figure& src) : multiplier(src.multiplier) {}
public:
virtual Figure* clone()=0;
double area() { return varea()*multiplier; }
};

class Square: public Figure {
private:
virtual double varea() {return L*L;}
double L;
public:
Square(const Square & src) : Figure(src), L(src.L) {}
virtual Figure* clone() {return new Square(*this);}
};

Обратите внимание:

  • я сделал Square::varea() частный, потому что так заявлено в классе Figure, Представление частного метода родительского класса как общедоступного в производном классе, как правило, немного сомнительно.
  • Есть проблема с оператором присваивания. Я оставлю это на ваше усмотрение.
  • Вам нужен какой-то способ установить multiplier,
1

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

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

struct Base
{
public:
Base()=default;
virtual ~Base()=default;

virtual Base* clone()=0;

Base& operator=(Base const &) = delete;
Base(Base&&)=delete;
protected:
Base(Base const&) = default;
};

struct Derivated : Base
{
public:
Derivated()=default;

virtual Derivated * clone()
{
return new Derivated (*this);
}
protected:
Derivated(Derivated const&) = default;
};
1

Добавьте защищенные средства доступа к классу фигур:

protected:
double getMultiplier() { return multiplier; }
void setMultiplier(double newValue) { multiplier = newValue; }

чем вы будете иметь доступ к множителю, хотя у вас не будет прямого доступа к члену ..

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