2016-01-09 3 views
-1

Вывод этой программы:Не могли бы вы помочь объяснить результат программы на C++?

A :: Fun C :: Do

Почему это не так:

A :: Fun A :: сделать

В основном это касается того, как работает виртуальная функция, но я не так хорошо знаком с ней, на самом деле я полностью новичок на C++, вам действительно нужно ваше терпение, чем кс.

#include <iostream> 
using namespace std; 

class A { 
private: 
    int nVal; 
public: 
    void Fun() { cout << "A::Fun" << endl; } 
    void Do() { cout << "A::Do" << endl; } 
}; 

class B :public A { 
public: 
    virtual void Do() { cout << "B::Do" << endl; } 
}; 

class C :public B { 
public: 
    void Do() { cout << "C::Do" << endl; } 
    void Fun() { cout << "C::Fun" << endl; } 
}; 

void Call(B &p) { 
    p.Fun(); 
    p.Do(); 
} 

int main() { 
    C c; 
    Call(c); 
} 
+1

Соблюдайте все предупреждения и информацию об отладке ('g ++ -Wall -Wextra -g') и ** используйте отладчик ** (' gdb') для выполнения вашей программы шаг за шагом. Читайте о [динамической рассылке] (https://en.wikipedia.org/wiki/Dynamic_dispatch) и [таблице виртуальных методов] (https://en.wikipedia.org/wiki/Virtual_method_table) –

ответ

2

ни функция виртуальная в А.

Так B мы имеем:

  • виртуальный Do и
  • наследственного невиртуальный Fun.

p.Fun 

довольно ясно, что вызывает A::Fun.


p.Do 

он называет C::Fun, потому что:

  • Do виртуальна в B,
  • C переопределяет Do
  • p является ссылочным типом
+0

Спасибо за ваше блестящее объяснение. – Stellera

1

Вызов p.Fun() разрешается до A::Fun() во время компиляции. Поскольку он не является функцией virtual, A::Fun() также запускается во время выполнения.

Звонок p.Do() получает разрешение B::Do() во время компиляции. Так как это функция virtual, и тип, соответствующий реальному объекту, C, имеет переопределенную реализацию, C::Do() получает исполнение во время выполнения.

+0

Спасибо, что так много. – Stellera

0

Выход оказывается

A::Fun 
C::Do 

Причина в том, B наследует от A, а затем класс B не имеет функции своей собственной называется fun так что вполне ожидаемо. Переход к следующему выводу. Оказывается, что даже если ссылочный класс B вызывает Do, он становится вызовом производного класса C, почему это так?

Когда метод становится виртуальным, вызов больше не определяется типом данных объекта, вызывающего его, скорее это адрес, который решает вызов этого метода. Поскольку метод Do является виртуальным. звонок теперь по адресу, адрес в основном принадлежит «C», поэтому вызывается CDo, надеюсь, вы его получили.

+1

Большое спасибо. Я думаю, что у меня это есть, функция вызова имеет объект типа B в качестве аргумента, а его адрес принадлежит «C». – Stellera