TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.35K subscribers
Post #270 3.87K
Вызов переопределенных методов в конструкторе / деструкторе

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

Вот, например, теперь мы можем в базовом классе выполнить переопределенный виртуальный метод наследованного класса:
struct base_t
{
    virtual const char* name() const
    {
        return "I'm base!";
    }
   
    void call_me()
    {
        std::cout << name() << std::endl;
    }

virtual ~base_t() = default;
};

struct derived_t : base_t
{
const char* name() const override
{
        return "I'm derived!";
  }
};

void main()
{
derived_t object;

// Выводит "I'm derived!"
object.call_me();
}

Базовый класс знает, что метод name() - виртуальный, поэтому используя встроенный механизм виртуальных таблиц, будет вызвано его переопределение.

Далее следует интересный вопрос, что будет если вызвать метод call_me из конструктора или деструктора?
virtual ~base_t()
{
call_me();
}

Виртуальный деструктор будет вызван в момент выхода тела main. Вероятно, что вы ожидаете увидеть имя из derived_t, ведь метод был переопределен. Давайте проверим в живом примере 1. Спойлер: вывелось из base_t. Почему?

Такое ограничение при вызове переопределенных методов связано с жизненным циклом объекта и порядком выполнения конструкторов и деструкторов:
Constructors:
base() -> derived_1() -> derived_2() -> ...;

Destructors:
... -> ~derived_2() -> ~derived_1() -> ~base();

Следовательно, и состояние данных в классах тоже зависит от порядка инициализации / разрушения классов.

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

Сделал живой пример 2, в котором постарался наглядно продемонстрировать, что при прямом вызове перегруженной реализации мы бы прочитали невалидные данные. Если что, так делать нельзя 😉 Тут важно просто понять мотивацию ограничений.

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

#cppcore
  • 🔥 30
  • ⚡ 13
  • 👍 7
  • ❤ 5
  • 🐳 1
More from @grokaemcpp
  1. Oct 14, 2026​​Что внутри std::condition_variable? #опытным Более менее все знакомы с примитивом синхро…
  2. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  3. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  4. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  5. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  6. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →