перегрузка функции с производным классом - PullRequest
1 голос
/ 20 сентября 2019

У меня есть следующий пример.Обратите внимание, что это просто пример, чтобы проиллюстрировать проблему.Реальная ситуация намного сложнее.

Проблема в том, что я должен перегрузить функцию из base класса.Если объект, используемый для вычисления, имеет тип base , он использует переменную x, которая является общей как для базового, так и для производного класса.Если объект имеет класс производный , он использует свою специфическую переменную y.Таким образом, реальная проблема заключается в , как определить производный класс до того, как будет определена базовая класс .

Я знаю два обходных пути проблемы, но ни один из них не является решением:

  • делает класс производным базовым классом и лишенными преимуществами наследования
  • изменение функции вычисляет до calculate(double y) {return x+y;), что означает, что решение, но не связано с проблемой, является очень сложным.Просто мне нужен доступ к остальной части объекта.
class base {
protected:
    double x;
public:
    double calculate(base b) {return x+b.x;}
    double calculate(derived d) {return x+d.y;}

}

class derived: base {
public:
    double y;

Эта проблема разрешима?

заранее спасибо ...

1 Ответ

4 голосов
/ 20 сентября 2019

Объявление вперед 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).

...