2016-09-24 3 views
-2

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

#include <stdio.h> 
#include <iostream> 

class Base { 
    public: 
     Base(){ 
      std::cout<<"Constructing Base" << std::endl; 
     }; 
     virtual int get_a(){ 
      return p_a; 
     }; 
     virtual int check(){ 
      std::cout<<"check Base" << std::endl; return 2; 
     }; 
     virtual ~Base(){ 
      std::cout<<"Destroying Base" << std::endl; 
     }; 
     int p_a = 4; 
}; 

class Derive: public Base { 
    public: 
     Derive(){ 
      std::cout<<"Constructing Derive" << std::endl; 
     }; 
     int get_a(){ 
      return p_a; 
     }; 
     int check(){ 
      std::cout<<"check Derive" << std::endl; 
      return 3; 
     }; 
     ~Derive(){ std::cout<<"Destroying Derive" << std::endl; }; 
     int p_a = 2; 
}; 

int main() { 
     Base *basePtr = new Derive(); 
     delete basePtr; 
     basePtr->check(); 
     std::cout << "p_a: " << basePtr->get_a() << std::endl; 
     return 1; 
} 

Консоль вывод:

Constructing Base // line 1 
Constructing Derive // line 2 
Destroying Derive // line 3 
Destroying Base  // line 4 
check Base   // line 5 
p_a: 4    // line 6 

Я понимаю, почему я получаю линию 1-4, то basePtr является указателем на Выведите, который наследует от базы, который реализует виртуальные функции.

Мое 1. ожидание: после звонка удалите, указатель basePtr не сможет доставить вызов функции -> check(), а также не должно быть значения p_a.

My 2. expectation: Я бы ожидал, что значение p_a из Derive (p_a = 2) появится на выходе, поскольку basePtr хранит указатель Derive.

Может ли кто-то исправить мои мысли?

+0

Вот почему рекомендуется всегда указывать указатель, который вы только что удалили, в nullptr. –

+0

* Указатель basePtr не должен доставлять вызов функции -> check(), * - Почему нет? Ваш код говорит, чтобы это сделать, и вот что произошло. Если вы скажете C++ что-то сделать, он сделает это, независимо от того, хотите ли вы, чтобы вы этого требовали, может потребоваться нежелательные результаты. – PaulMcKenzie

+0

@BasinhetVeld: Uhm ... вот почему вы ** не ** используете указатели на C++ вообще. Объекты с автоматической продолжительностью хранения отличные, включая интеллектуальные типы указателей, такие как 'std :: unique_ptr'. – IInspectable

ответ

2

Это неопределенное поведение. Независимо от результатов, которые вы получили, они недействительны.

delete basePtr; 

Это разрушает объект.

basePtr->check(); 

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

Смежные вопросы