2016-06-14 3 views
-1

Ich habe nächsten Code:C++ Ich kann nicht verstehen, warum es „Vater Klasse statische Funktion“ nennen und nennt es nur Vater destructor

#include <iostream> 

using namespace std; 

class A{ 
public: 
    A() { cout << "A() ";} 
    virtual void f()=0; 
    virtual void g() { cout << "ag() ";} 
    static void h() { cout << "ah() ";} 
    void i() { cout << "ai() ";} 
    ~A() { cout << "~A() "; } 
}; 

class B: public A{ 
    void f() { cout << "bf() ";} 
public: 
    void g() { cout << "bg() ";} 
}; 

class C: public B{ 
public: 
    static void h() { cout << "ch() "; } 
    void g() { cout << "cg() ";} 
    ~C() { cout << "~C() ";} 
}; 

void f1(){ 
    B b; 
    C c; 
    b.h(); 
    c.h(); 
    A* arr[2] = { new B ,new C}; 
    arr[0]->h(); 
    arr[1]->h(); 
    delete arr[0]; 
    delete arr[1]; 
} 


int main(){ 
    f1(); 
    return 0; 
} 

Ich kann nicht verstehen, warum es eine druckt() A() ah() ch() A() A() ah() ah() ~ A() ~ A() ~ C() ~ A() ~ A() und es wird nicht gedruckt A() A() ah() ch() A() A() ah() ch() ~ A() ~ A() ~ C() ~ A() ~ C(). Kann mir jemand helfen?

+3

Sieht aus wie etwa 90% dieses Codes (und 90% der Ausgabe) hat nichts mit der Frage zu tun. –

+2

TL; DR: Destruktoren sollten virtuelle, statische Funktionen können nicht virtuell sein. –

+2

Respektieren Sie die Zeit der Menschen, die Ihnen hier helfen, und verbringen Sie ein wenig Zeit damit, die Teile zu entfernen, die Sie * nicht * verwirrend finden, bevor Sie nach dem Rest fragen. – Yakk

Antwort

1

Zuerst haben Sie vergessen, den Destruktor von A virtuell zu deklarieren. Aus diesem Grund hat das Löschen eines abgeleiteten Objekts durch einen Zeiger A undefiniertes Verhalten. Ein mögliches Ergebnis von undefiniertem Verhalten ist, dass ~C() nicht gedruckt wird (und auch Speicher verloren gegangen ist). Ein vernünftiger Compiler hätte Sie davor gewarnt, es sei denn, Sie hätten vergessen, Warnungen zu aktivieren.

Lösung: Löschen Sie die Objekte nicht durch einen Basisklassenzeiger oder machen Sie den Destruktor der Basisklasse virtuell.

Zweitens wird ch() nicht gedruckt, wenn Sie arr[0]->h() nennen, weil der statische Typ von arr[0] nicht C*, aber A*. Der virtuelle Versand wird nicht verwendet, da die Funktion nicht virtuell ist. Und es kann nicht virtuell sein, weil es eine statische Elementfunktion ist. Statische Memberfunktionen können nicht überschrieben werden.

Lösung: Passen Sie Ihre Erwartungen an.

+0

Ich bereite mich auf Prüfung vor Ich habe versucht, ein Thema zu lösen. Lehrer geben uns einige Codebeispiele und wir müssen schreiben, was der Code tut. Sie sagten, dass arr [0] A * Typ ist, also frage ich, warum A und C Destruktor auch für arr [1 aufrufen ]? – xSLive

+0

Meinst du, dass 'delete arr [1];' würde 'A' und' C' Destruktor nennen? Nun, das ist nicht, was Sie in der Ausgabe sehen. Achten Sie mehr darauf, welche Ausgabe von welcher Aussage kommt durch den Code mit einem Debugger. – user2079303

+0

Ich verstehe. ~ C() und ~ A() ist von 'C c' Destruktor. Danke. – xSLive

0

Dies liegt daran, arr ist ein Array, das Zeiger auf A Klasseninstanzen enthält.

Daher ruft Aufruf arr[0]->h()A::h() auf. h() ist keine virtuelle Klassenmethode. Sie verstehen natürlich, wie die virtuelle Vererbung funktioniert und wie virtuelle Funktionen ihre Basisklassenversionen überschreiben. Damit die virtuelle Vererbung funktioniert, muss die Funktion jedoch tatsächlich mit dem Schlüsselwort virtual deklariert werden. Sie sehen nicht das Schlüsselwort virtual, das zur Deklaration der Klassenmethode h() verwendet wird, also, warum erwarten Sie, dass h() wie eine virtuelle Funktion funktioniert?

In der Tat, weil h() eigentlich eine static Klasse Funktion ist, dann

arr[0]->h(); 
arr[1]->h(); 

genau entspricht:

A::h(); 
A::h(); 

Der Compiler stört nicht einmal den Code zu kompilieren, der die arr[0] abruft und arr[1] Zeiger, weil sie irrelevant sind. this wird natürlich nicht von static Klasse Methoden verwendet, so dass es keine Zeit verschwenden muss herauszufinden, was this sein sollte.

+0

Nur um zu verdeutlichen, ich spreche den spezifischen Punkt zitiert, dass die tatsächliche Ausgabe ist "...ah() ah() ... "anstelle dessen, was OP erwartet, was" ... ah() ch() ... "ist. –

+0

" Wie virtuelle Vererbung funktioniert "wo? – curiousguy

Verwandte Themen