2015-12-06 2 views
1

Я занимаюсь некоторым упражнением на своем понимании. при компиляции ниже кода я вызываю Derived :: disp() и который, в свою очередь, вызывает не виртуальную функцию «Печать».Поведение виртуальной функции C++

Мой вопрос: почему версия производного класса «Печать» вызывается вместо базовой версии печати, даже «Печать» не является виртуальной.

class Base 
{ 
public: 
    void print(){ 
     cout<<"Base::Print()\n"; 
    } 
virtual void disp(){ 
    cout<<"Base::Disp()\n"; 
    } 
}; 

class Derived: public Base 
{ 
public: 
    void print(){ 
     cout<<"Derived::Print()\n"; 
    } 
    void disp(){ 
    cout<<"Derived::Disp()\n"; 
    print(); 
    } 
}; 

void main() 
{ 
    Base *pB = new Derived(); 

    pB->disp(); 
} 

выход:
Derived :: Disp()
Derived :: Print()

+0

Должно ли это быть 'int main' –

ответ

5

Если у вас есть вызов на NON-виртуальной функции внутри (виртуального или не виртуальной) члена функция, вызывается функция-член этого класса.

Если вы хотите позвонить в pB->print() в главном, это будет звонить по телефону Base::Print. Но в его нынешнем виде pB->Disp() звонит Derived::Disp(), который вызывает Derived::Print на основании того, что он вызывается изнутри класса Derived.

1

Внутри тела нестатической функции-члена ключевое слово this имеет тип указателя на объект типа класса, для которого вызывается функция.

Если виртуальная функция вызывается для производного класса, то this имеет тип указателя этого класса.

Внутри функций членов доступа к членам класса выглядит, например, в контексте вашей программы, как

(*this).print(); 

где this имеет тип Derived *.

Таким образом, функция-член print этого класса.

+0

Что произойдет, если базовый класс N-виртуальная функция вызывает виртуальную функцию базы – Raj

+1

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

0

К компилятору виртуальное означает, что для вызовов этой функции сначала следует проконсультироваться с v-таблицей, чтобы найти реальное местоположение для этой функции, а не использовать статический тип экземпляра. При этом ваш вызов disp() достигает кода в Derived. В полученном, вы можете вызвать функцию печати базового класса с:

Base::print(); 

Но по умолчанию, печати() будет вызывать Derived :: печати(). Скачок v-таблицы уже выполнен, поэтому в этой функции известен статический тип «this». Это помогает думать о классе макета в C++:

Derived { 
    Base { 
    print(); 
    virtual disp(); 
    } 
    print(); 
    disp(); 
} 

виртуальный требуется для первого вызова, потому что компилятор видит базу, поэтому из основных, если вы звоните РВЛ> Print(), это будет выглядеть при смещении, соответствующем функции печати, тогда как для disp он найдет запись v-таблицы и перейдет через это в Derived :: disp().

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