Объявление вперед derived
с последующим определением тел calculate
вне строки после определения derived
должно работать:
class derived;
class base {
protected:
double x;
public:
double calculate(base b);
double calculate(derived d);
}
class derived: base {
public:
double y;
};
inline double base::calculate(base b) {return x+b.x;}
inline double base::calculate(derived d) {return x+d.y;}
Как уже говорили другие, это может быть плохой дизайн с base
требующих знания derived
.Возможно, calculate
будет лучше в качестве бесплатной функции:
class base {
public:
double x;
}
class derived: base {
public:
double y;
};
inline double calculate(base a, base b) {return a.x+b.x;}
inline double calculate(base a, derived b) {return a.x+b.y;}
Я сделал x
общедоступным, чтобы упростить пример, вы можете сделать расчет друга (что снова потребует знания derived
class в base
) или функцию доступа, если вы не хотите, чтобы x
был общедоступным.
Третий вариант - добавление виртуального метода для получения требуемого значения для каждогоclass:
class base {
protected:
double x;
virtual double getValue() const { return x; }
public:
double calculate(const base& b) { return x + b.getValue(); }
}
class derived: public base {
protected:
double getValue() override const { return y; }
private:
double y;
};
Обратите внимание, что calculate
должен брать класс по ссылке, чтобы избежать среза объекта (и его более эффективной).
В зависимости от ваших требований вычисление может быть лучше реализовано как:
double calculate(const base& b) { return getValue() + b.getValue(); }
Это будет означать, что base.calculate(derived)
вернет тот же результат, что и derived.calculate(base)
.