переопределить виртуальный метод c++

У меня есть шаблон класса, где некоторые методы определены как виртуальные, чтобы дать возможность пользователю моего класса дать реализацию для них в его производном классе. Обратите внимание, что в моем классе шаблонов есть некоторые не виртуальные методы, которые используют виртуальный (виртуальный класс, который должен возвращать значение, вызывается в не виртуальном классе).

можете ли вы дать мне простой пример корректного кода, где виртуальный метод родительского класса должны возвращать значение (но его реализация предоставляется в дочернем классе), а значение, возвращаемое виртуальным методом в родительском классе, используется в других методах этого класса. Потому что я где-то видел (например здесь:безопасное переопределение виртуальных функций C++), что это может вызвать некоторые проблемы и пользовательских метода Примечание переопределить виртуальный метод родительского класса.

Примечание: я программирую с помощью Code:: Blocks с помощью компилятора g++.

EDIT: по просьбе здесь просто пример того, что я хочу:

template<typename T>
class parent {
public:
  // Public methods that user can call
  int getSomething(T t);
  void putSomething(T t, int x);

  // public method that user should implement in his code
  virtual float compute(T t) { }

  // protected or private methods and attributes used internally by putSomething ...
  float doComplexeThings(...); // this can call
};

метод compute () должен быть реализован пользователем (дочерним классом). Однако этот метод compute() вызывается, например, putSomething() и doComplexeThings ().

3 ответов


вы просто должны убедиться, что методы имеют одинаковую подпись (включая модификаторы const/mutable и типы аргументов). Можно использовать чисто виртуальное определение, чтобы вызвать ошибки компилятора, если не удается переопределить функцию в подклассе.

class parent {
public:
  // pure virtual method must be provided in subclass
  virtual void handle_event(int something) = 0; 
};

class child : public parent {
public:
  virtual void handle_event(int something) {
    // new exciting code
  }
};

class incomplete_child : public parent {
public:
  virtual void handle_event(int something) const {
    // does not override the pure virtual method
  }
};

int main() {
  parent *p = new child();
  p->handle_event(1); // will call child::handle_event
  parent *p = new incomplete_child(); // will not compile because handle_event
                                      // was not correctly overridden
}

Если вы можете использовать функции C++11 в своем компиляторе, то переопределения могут быть помечены как override специальный идентификатор:

 float compute() override;

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

из базового класса вы можете только силу переопределение, сделав функцию чисто виртуальной, но это изменяет семантику. Это не избежать проблемы при переопределении, а скорее сил переопределение во всех случаях. Я бы избегал этого подхода, и если вы будете следовать ему и есть разумная реализация для базового типа, сделайте функцию virtual и укажите определение, чтобы реализация производных классов могла просто вызывать функции базового типа (т. е. вы форсируете реализацию, но в простейших случаях она просто переадресует вызов родительскому)


этот вопрос задан в 2013 году. Он довольно старый, но я нашел что-то новое, чего нет в ответах.

нам нужно понять три понятия перегрузка, перезаписать и скрыть.

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

class A {
public:
  virtual void print() {
    cout << id_ << std::endl;
  }
private:
  string id_ = "A";
};

class B : A {
public:
  using A::print;
  void print(string id) {
    std::cout << id << std::endl;
  }
};

int main(int argc, char const *argv[]) {
  /* code */
  A a;
  a.print();
  B b;
  b.print();
  b.print("B");
  return 0;
}

добавить использование A:: print; в вашем производном классе будет делать работу!

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