CPLUSPLUC Telegram 1066
🦾 Задача с подвохом: Виртуальные функции и конструкторы

Условие:

Что выведет следующий код и почему?


#include <iostream>

class Base {
public:
Base() {
std::cout << "Base constructor\n";
foo();
}
virtual void foo() {
std::cout << "Base foo\n";
}
};

class Derived : public Base {
public:
Derived() {
std::cout << "Derived constructor\n";
}
void foo() override {
std::cout << "Derived foo\n";
}
};

int main() {
Derived d;
return 0;
}


Вопрос:
Что будет выведено? Почему результат может удивить даже опытных C++ разработчиков?

🔍 Разбор:

1️⃣ Мы создаём объект
Derived d;.
Это вызывает конструктор
Derived, но сначала выполняется конструктор `Base` (по правилам иерархии).

2️⃣ В конструкторе
Base есть вызов foo();.
Может показаться, что поскольку объект на самом деле
Derived, вызовется Derived::foo().

Но! Вот главный подвох:

➡️ В C++, когда вы вызываете виртуальную функцию из конструктора (или деструктора), она не виртуальна для объекта, который ещё не полностью сконструирован.

На момент вызова
foo() объект всё ещё только Base, потому что Derived ещё не инициализирован.

Пошаговое выполнение:

- Вызов конструктора
Base:
```
Base constructor
```
- Вызов
foo() внутри конструктора Base:
Это вызовет Base::foo(), а не
Derived::foo():
```
Base foo
```
- После завершения конструктора
Base, вызывается конструктор Derived:
```
Derived constructor
```

Итоговый вывод:

```
Base constructor
Base foo
Derived constructor
```

💥 Подвох:

• Многие ожидают, что виртуальные функции работают «магически» всегда.
• Но при вызове из конструктора (или деструктора) виртуальные функции не полиморфны, потому что объект ещё не «стал» Derived полностью.

🛡️ Что нужно помнить:

Никогда не полагайтесь на вызовы виртуальных функций в конструкторах/деструкторах для вызова методов производных классов. Это источник трудноуловимых багов.

Вывод:

C++ строго следует правилам объектной модели: пока объект конструируется (или разрушается), он считается экземпляром того класса, конструктор которого выполняется в данный момент. Это поведение важно помнить при проектировании иерархий классов!


@cpluspluc



tgoop.com/cpluspluc/1066
Create:
Last Update:

🦾 Задача с подвохом: Виртуальные функции и конструкторы

Условие:

Что выведет следующий код и почему?


#include <iostream>

class Base {
public:
Base() {
std::cout << "Base constructor\n";
foo();
}
virtual void foo() {
std::cout << "Base foo\n";
}
};

class Derived : public Base {
public:
Derived() {
std::cout << "Derived constructor\n";
}
void foo() override {
std::cout << "Derived foo\n";
}
};

int main() {
Derived d;
return 0;
}


Вопрос:
Что будет выведено? Почему результат может удивить даже опытных C++ разработчиков?

🔍 Разбор:

1️⃣ Мы создаём объект
Derived d;.
Это вызывает конструктор
Derived, но сначала выполняется конструктор `Base` (по правилам иерархии).

2️⃣ В конструкторе
Base есть вызов foo();.
Может показаться, что поскольку объект на самом деле
Derived, вызовется Derived::foo().

Но! Вот главный подвох:

➡️ В C++, когда вы вызываете виртуальную функцию из конструктора (или деструктора), она не виртуальна для объекта, который ещё не полностью сконструирован.

На момент вызова
foo() объект всё ещё только Base, потому что Derived ещё не инициализирован.

Пошаговое выполнение:

- Вызов конструктора
Base:
```
Base constructor
```
- Вызов
foo() внутри конструктора Base:
Это вызовет Base::foo(), а не
Derived::foo():
```
Base foo
```
- После завершения конструктора
Base, вызывается конструктор Derived:
```
Derived constructor
```

Итоговый вывод:

```
Base constructor
Base foo
Derived constructor
```

💥 Подвох:

• Многие ожидают, что виртуальные функции работают «магически» всегда.
• Но при вызове из конструктора (или деструктора) виртуальные функции не полиморфны, потому что объект ещё не «стал» Derived полностью.

🛡️ Что нужно помнить:

Никогда не полагайтесь на вызовы виртуальных функций в конструкторах/деструкторах для вызова методов производных классов. Это источник трудноуловимых багов.

Вывод:

C++ строго следует правилам объектной модели: пока объект конструируется (или разрушается), он считается экземпляром того класса, конструктор которого выполняется в данный момент. Это поведение важно помнить при проектировании иерархий классов!


@cpluspluc

BY C++ Academy


Share with your friend now:
tgoop.com/cpluspluc/1066

View MORE
Open in Telegram


Telegram News

Date: |

Don’t publish new content at nighttime. Since not all users disable notifications for the night, you risk inadvertently disturbing them. The initiatives announced by Perekopsky include monitoring the content in groups. According to the executive, posts identified as lacking context or as containing false information will be flagged as a potential source of disinformation. The content is then forwarded to Telegram's fact-checking channels for analysis and subsequent publication of verified information. ‘Ban’ on Telegram Just at this time, Bitcoin and the broader crypto market have dropped to new 2022 lows. The Bitcoin price has tanked 10 percent dropping to $20,000. On the other hand, the altcoin space is witnessing even more brutal correction. Bitcoin has dropped nearly 60 percent year-to-date and more than 70 percent since its all-time high in November 2021. Add up to 50 administrators
from us


Telegram C++ Academy
FROM American