Проблема
Программа имеет Неопределенное поведение . b
находится только в области видимости тела if
. Вы не можете рассчитывать на логические результаты при доступе к висячему указателю .
int main()
{
A* a;
if (true) {
B b; // b is scoped by the body of the if.
a = &b;
} // b's dead, Jim.
std::cout << a->foo() << std::endl; // a points to the dead b, an invalid object
return 0;
}
TL; DR Solution
int main()
{
std::unique_ptr<A> a; // All hail the smart pointer overlords!
if (true) {
a = std::make_unique<B>();
}
std::cout << a->foo() << std::endl;
return 0;
} // a is destroyed here and takes the B with it.
Объяснение
Youможет указывать a
на объект с динамическим временем жизни
int main()
{
A* a;
if (true) {
a = new B; // dynamic allocation
} // b's dead, Jim.
std::cout << a->foo() << std::endl;
delete a; // DaANGER! DANGER!
return 0;
}
К сожалению, delete a;
также является неопределенным поведением, потому что A
имеет деструктор не virtual
. Без виртуального деструктора объект, на который указывает a
, будет уничтожен как A
, а не как B
.
. Исправление для этого - дать A
виртуальный деструктор, чтобы позволить емууничтожить правильный экземпляр.
class A {
public:
virtual ~A() = default;
virtual int foo() {
return 0;
}
private:
std::string my_string;
};
Нет необходимости изменять B
, поскольку после объявления функции virtual
она остается virtual
для своих дочерних элементов. Следите за final
.
Но лучше всего избегать необработанных динамических выделений , поэтому мы можем сделать еще одно улучшение: ИспользованиеУмные указатели .
И это возвращает нас к решению.
Документация для std::unique_ptr
Документация для std::make_unique