2017-02-16 16 views
2

Я рассматриваю пример поведения виртуальных функций. Учитывая этот тестовый код, у меня есть несколько вопросов относительно его поведения.Подпись виртуальной функции Несоответствие и ее поведение

class A 
{ 
public: 
    A(int x) 
    { 
     cout << "In A Constructor" << endl; 
     print(); 
    } 
    ~A(){ 
     cout << "In A Destructor" << endl; 
     delete _val; 
    } 
    virtual void print() { cout << "A." << endl; } 
private: 
    char* _val; 
}; 

class B: public A 
{ 
public: 
    B(int x, int y) : A(x) 
    { 
     _dVal = new char[y]; 
     cout << "In B Constructor 1" << endl; 
     print(); 
    } 
    B() : A(0) 
    { 
     _dVal = new char[1]; 
     cout << "In B Constructor 2" << endl; 
     print(); 
    } 
    ~B(){ 
     cout << "In B Destructor" << endl; 
     delete _dVal; 
    } 
    void print() { cout << "B" << endl; } 
private: 
    char* _dVal; 
}; 

int main(int argc, char** argv) { 
    A* p1 = new B(); 
    p1->print(); 
    delete p1; 
    return 0; 
} 

Выход:

In A Constructor 
A. 
In B Constructor 2 
B 
B 
In A Destructor 

1) Почему печать называется класса В, если класс А является единственным обозначив ее как виртуальную функцию и она вызывается с помощью разыменования (->)? 2) Почему деструктор для B не вызывается, если на самом деле вызывается конструктор?

+1

Если функция является виртуальной в базовом классе, она также является виртуальной во всех производных классах. То же самое для деструктора. –

+1

Один вопрос на вопрос прошу. –

ответ

4

1) Почему печать называется классом B, если класс A является единственным, обозначающим его как виртуальную функцию и вызываемый разыменованием (->)?

Это то, что должны делать виртуальные функции. Указатель p1 имеет тип A*, но он указывает на объект типа B. И это динамическое связывание происходит только тогда, когда производный класс обрабатывается с помощью указателя или ссылки на базовый класс.

Также обратите внимание, что функция переопределения в производном классе также является virtual (независимо от того, используется ли ключевое слово virtual в его объявлении).

2) Почему деструктор для B не вызывается, если на самом деле вызывается конструктор?

Деструктор B не называется, потому что вы не объявить деструктор базового класса (т.е. A::~A) в качестве virtual destructor. Для этого случая поведение не определено. Конструктор B вызывается, потому что вы автоматически создаете B на new B().

+0

Интересно. Так как поведение не определено, означает ли это, что _dVal из класса B станет oprhan и вызовет утечку памяти? – w0ffen

+0

@ user49096 Из результата, который вы наблюдали, да. Обратите внимание, что это неопределенное, все возможно. – songyuanyao

+0

@ user49096 «Поскольку поведение не определено, означает ли это, что« нет », это означает, что события не определены, неопределены, неизвестны ... – curiousguy

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

  • Нет связанных вопросов^_^