2015-06-14 6 views
1

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

class A 
{ 
public: 
    A() {std::cout<<"A()";} 
    virtual ~A(){std::cout<<"~A()";} 

    virtual void print() {std::cout<<"A";} 
}; 

class B : public A 
{ 
public: 
    B() {std::cout<<"B()";} 
    virtual ~B(){std::cout<<"~B()";} 

    virtual void print() {std::cout<<"B";} 
}; 

И следующие фрагменты кода:

void f3() 
{ 
    A a[2]; 
    a[1]=B(); 
    a[1].print(); 
} 

И результат я думаю, что его:

A() A() 
A() B() {not sure why there is an A() too) 
A - and here I really don't know because either A and B are virtual(and I have in the notebook A) 
~B() ~A() 
~A() ~A() 

И еще фрагменты кода:

void f4() 
{ 
    A* a[]={new A(), new B()}; 
    a[0]->print(); 
    a[1]->print(); 
    delete a[0]; 
    delete a[1]; 
} 

А вот и проблема. У нас есть

A() {here I don t know why there is an A()} 
A() B() 
A 
B 
~B() ~A() 
A() 

Но это правильно? И почему здесь мы имеем A и B, а не B и A? Я имею в виду, что в первом упражнении у меня есть A, когда это был тип B(), и вот, как я считаю, что это нормально, но почему?

+2

y u no 'A(). Print(); B(). Print(); ' – rightfold

+0

Чтобы было легче понять, что происходит, когда и почему я, как правило, просто нажимаю на компилятор, как здесь: http://ideone.com/SWiNmn Там вы видите, какая именно строка вызывала, какая инструкция , – Michael

+0

Спасибо. Вы мне очень помогли. – Boolean

ответ

2
A() A() 

Вы создали массив из двух A, поэтому два вызова A ctor.

A() B() {not sure why there is an A() too) 

Вы создали B (B()) и Bs порождаются от As, поэтому шаги: выделение памяти для хранения B, вызов CTOR для А-части, вызов CTOR B для B-часть.

A - and here I really don't know because either A and B are virtual(and I have in the notebook A) 

Вы назначен свежий созданный B к A, так что это вызывает копию А-части B до назначения А. Тогда вы назвали print на А, и это печатает A.

~B() ~A() 
~A() ~A() 

dtors вызывается в точном обратном порядке.

Во второй попытке вы используете указатели и динамические распределения, и в этом случае используется полиморфизм. Ваш массив представляет собой массив из двух указателей на тип A, инициализированный (адресом) двумя объектами: первый начинается с A, второй a B.

Когда вы вызываете a[0]->print(), a[0] является адресом A, поэтому вызывается метод print.

Когда вы звоните a[1]->print(), a[1] является адрес B, поэтому метод print его называют, потому что print является virtual.

+1

Я думаю, что последние два примера относятся к случаю указателя в последнем примере, а затем должны быть [0] -> print() и [1] -> print() соответственно. – Michael

+0

Спасибо за объяснение :) Я наконец понял, как это работает. – Boolean

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