Обновление
На основании вашего комментария ниже о том, что вы пытаетесь заставить doSomething () вызвать версию start () и stop () класса производного, мой обновленный ответ на ваш вопрос выглядит следующим образом:
Нет ничего плохого в том, как вы определили Base и Derived. Вы, вероятно, испытываете то, что называется «нарезкой кода», когда вы вызываете «doSomething ()» для объекта, объявленный тип которого «Base» вместо «Base *» или «Base &», что приведет к тому, что объект будет преобразован в тип Base.
Плохой пример:
Derived derived;
Base base = derived;
base.doSomething(); // This is Base's version of doSomething()
Хороший пример:
Base* base = new Derived; // NOTE: declared type is "Base*"
base->doSomething(); // This will call Derived version
delete base;
Примечание: вы должны использовать scoped_ptr, shared_ptr, unique_ptr или какой-либо другой класс интеллектуальных указателей вместо прямого указателя, как в моем примере; однако, чтобы не затенять проблему, я решил использовать необработанный указатель в этом примере. Для получения дополнительной информации о «нарезке» см .:
Оригинальное решение
Вы могли бы сделать что-то вроде этого:
class Base {
public:
Base() {}
virtual ~Base() {}
virtual void start() {
startInternal();
}
virtual void stop() {
stopInternal();
}
void doSomething() {
startInternal();
// ...
stopInternal();
}
private:
void startInternal() {
// ...
}
void stopInternal() {
// ...
}
};
class Derived : public Base {
public:
Derived() {}
virtual ~Derived() {}
virtual void start() {
// ...
}
virtual void stop() {
// ...
}
};
Если вы сделаете это, то doSomething () будет использовать внутреннюю версию start / stop, которая не переопределяется. Вы часто найдете этот шаблон, когда конструктор / деструктор должен разделить логику с виртуальным методом.
Кроме того, не относясь к рассматриваемой проблеме, не забывайте, что вы всегда должны создавать виртуальный деструктор всякий раз, когда создаете класс с виртуальными методами.