У меня есть абстрактный класс сказать 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 без необходимости сообщать каждой фигуре свой множитель.
Если вы не объявляете конструктор копирования для своего класса на безвозмездной основе, и это публично. Вам не нужен этот бесплатный конструктор публичных копий. Это приведет к нарезке. Создайте свой конструктор копирования для защищенного класса 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
,Наследование неловко связывается с семантикой копирования. Тем не менее, одно решение может позволить конструктору копирования выполнить эту работу:
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;
};
Добавьте защищенные средства доступа к классу фигур:
protected:
double getMultiplier() { return multiplier; }
void setMultiplier(double newValue) { multiplier = newValue; }
чем вы будете иметь доступ к множителю, хотя у вас не будет прямого доступа к члену ..