2015-06-25 2 views
1
#include <iostream> 

using namespace std; 
class A { 
public: 
    void m1(){ cout << 'A'; } 
    virtual void m2(){ cout << 'B'; } 
    virtual void m3(){ cout << 'C'; } 
}; 

class B: public A { 
public: 
    void m1(){ cout << 'D'; } 
    void m2(){ cout << 'E'; } 
}; 

class C: public B { 
public: 
    void m3(){ cout << 'F'; } 
}; 

int main() 
{ 
    cout << "Hello World!" << endl; 
    A* a = new B(); 
    a->m1(); 
    a->m2(); 
    a->m3(); 
    return 0; 
} 

Какой будет выход? Первоначально я думал, что это будет «DEC», но после запуска программы она была «AEC»информация о простом наследовании C++

Можно ли уточнить, что происходит за этой строки кода:

A* a = new B(); 
+3

m1() не является виртуальной в базовом классе А. Крепление, которое должно дать ожидаемый результат. – Mark

+3

Вы добавили ключевое слово 'virtual, знаете ли вы, что это такое? –

+0

-1 Это довольно глупо; вы, очевидно, просто случайно догадываетесь. Вы считали, что «виртуальный» не имеет никакой цели? Разве не удалось определить шаблон в выходе, который вы получаете? Или прочитайте свою книгу на C++? –

ответ

6

Виртуальные функции-члены отправляются на основе динамического типа (время выполнения). Не виртуальные функции-члены отправляются на основе статического объекта (время компиляции).

A *a = new B(); 

a указывает на объект, чей динамический тип B. Однако статический тип a равен A*, что означает, что статический тип *a равен A.

Виртуальные функции (m2 и m3) отправляются на основе динамического типа, так и B::m2B::m3 называются.

Не виртуальные функции отправляются на основе статического типа. Статический тип *a - A, поэтому вызывается A::m1.


Что именно происходит в линии new? Новый объект типа B создается динамически, а выражение new возвращает указатель на этот объект (типа B*). Затем преобразование с производной базой применяется к этому указателю для преобразования его в A*, который используется для инициализации переменной a.

В псевдокоде, показывая промежуточные шаги:

B *tmp_b = new B(); // allocate and initialise B object 
A *tmp_a = convert_derived_to_base(tmp_b); 
A *a = tmp_a; 
+1

Быстрые снимки не соответствуют устойчивому. +1! – Quentin

+0

поэтому компилятор сначала успешно инициализирует указатель на объект класса A: 'A * a', а затем динамически инициализирует указатель на объект класса B и переопределяет инициализированный символ' A * a' равным 'B *'? Мне нужно знать, что происходит под капотом. – tomtom

+0

@tomtom Я добавил шаги в форме кода. Там нет «переопределения». – Angew

1

m1 метод не является виртуальным в класс A, он не может быть переопределен .m2 является виртуальным, поэтому он переопределяет метод класса B.

1

Вывод будет

AEC 

Причина заключается в том, что A::m1 не был объявлен virtual. В этой строке

A* a = new B(); 

Вы объявляя A* переменную a, которая на самом деле является экземпляром производного класса B. Это разрешено, потому что «B - это тип A».

Когда функция объявлена ​​virtual, если производный класс определяет эту функцию, то в базовом классе переопределяется версия в производном классе. Таким образом, следующие вызовы будут

a->m1(); // A::m1 
a->m2(); // B::m2 
a->m3(); // A::m3 
0

Здесь Class A ваш родительский класс, так, чтобы переопределить метод родительского класса вы должны сделать его virtual в классе А. Так что метод Class B «s будет называться. Дополнительную информацию см. На странице Virtual Functions

0
void m1(){ cout << 'A'; } 
virtual void m2(){ cout << 'B'; } 
virtual void m3(){ cout << 'C'; } 

Выход полностью штраф в соответствии с вашим кодом программы.

void m1(){ cout << 'A'; не является виртуальной функцией. Так a->m1(); вызывает базовую версию m1 и дает o/p как A.

m2() это виртуальная функция, и она имеет новую реализацию внутри класса В. void m2(){ cout << 'E'; }

Так a->m2(); называет версию функции m2class B и дает выход E.

Нет новой реализации m3 внутри class B. So a->m3(); звонки m3, который унаследован от class A.

Чтобы получить о/р, как DEC нужно просто изменить функцию m1 к виртуальной функции, как показано ниже

class A { public: virtual void m1(){ cout << 'A'; } virtual void m2(){ cout << 'B'; } virtual void m3(){ cout << 'C'; } };

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