2017-03-20 7 views
8

Vor ein paar Tagen wollte ich in die C++ Welt eintauchen. Ich studiere die Grundlagen- und abgeleiteten Klassenkonzepte. Könnte jemand die Nuance mit den folgenden zwei Codeschnipsel erklären?Basis und abgeleitete Klassen C++

class A 
{ 
    private: 
    virtual int GetValue() { return 10; } 

    public: 
    int Calculate() { return GetValue()*1.5; } 
}; 

class B: public A 
{ 
    private: 
    virtual int GetValue() { return 20; } 
}; 

int main() 
{ 
    B b; 
    std::cout << b.Calculate() << std::endl; 

    return 0; 
} 

Der Ausgang ist 30, aber 15 wurde

erwartet
class A 
{ 
    private: 
    int m_data; 

    public: 
    A(): m_data(GetValue()) {} 
    int Calculate() { return m_data*1.5; } 
    virtual int GetValue() { return 10; } 
}; 

class B: public A 
{ 
    public: 
    virtual int GetValue() { return 20; } 
}; 

int main() 
{ 
    B b; A* ap; 
    ap=&b; 
    std::cout << ap->Calculate() << std::endl; 

    return 0; 
} 

Der Ausgang 15 ist aber 30 wurde

erwartet

Kann jemand erklären und mir helfen, die Gründe zu verstehen? Etwas stimmt nicht mit meinen Gedanken zu diesem Konzept, aber ich kann es nicht herausfinden.

+2

Erklären Sie, warum Sie dachten, dass Ihr Code diese Werte liefern würde. –

Antwort

5

Erster Fall:

Dies ist trivial. Sie haben eine instanziierte Instanz von B, und Sie berechnen return GetValue() * 1.5;, die B::GetValue() verwendet, wie Sie in der Basisklasse virtualvirtual markiert haben. Daher wird 20 * 1,5 ausgewertet.

Zweiter Fall:

Nicht so trivial. Sie rufen GetValue() in dem Base-Elementinitialisierer auf, um einen Wert für m_data festzulegen. Standard C++ schreibt vor, dass in diesem Fall die Basisklasse GetValue() aufgerufen wird. (Informieren Sie dies inoffiziell als der Klasse B, die nicht gebaut wird, bis die Klasse A vollständig aufgebaut ist). Daher wird 10 * 1,5 ausgewertet. Interessanterweise, wenn GetValue()rein virtuell war, dann wäre das Verhalten des Programms undefined gewesen.


Referenz: Why a virtual call to a pure virtual function from a constructor is UB and a call to a non-pure virtual function is allowed by the Standard?

+1

Ihre Antwort ist so hilfreich, klar und vollständig. Es war sehr wichtig für mich, dies zu verstehen, bevor ich weiterkomme. Ich danke dir sehr. Ich hab es jetzt. – Zizou23

2

Versuchen Sie den folgenden Code für das zweite Beispiel:

class A 
{ 
private: 
int m_data; 

public: 
A(): m_data(GetValue()) { std::cout << "Init m_data and A ";} 
int Calculate() { return m_data*1.5; } 
virtual int GetValue() { std::cout << "GetValue from A ";return 10; } 
}; 

class B: public A 
{ 
public: 
B() { std::cout << "Init B "; } 
virtual int GetValue() { std::cout << "GetValue from B"; return 20; } 
}; 

int main() 
{ 
B b; A* ap; 
ap=&b; 
std::cout << ap->Calculate() << std::endl; 

return 0; 
} 

Es ist das gleiche, wie Sie bereits haben, aber mit Ausgängen. Sie sollten GetValue from A Init m_data and A Init B 15 erhalten. Ich hoffe jetzt sehen Sie, warum Sie eine Ausgabe von 15 haben. Mit den Ausgaben sollten Sie in der Lage sein, die Ausführungsreihenfolge zu rekonstruieren.

Verwandte Themen