2017-12-11 1 views
1
#include <iostream> 
using namespace std; 


class foo 
{ 
private: 
    static int cnt; // number in memory 
    static int nextid; // the next id number 

public: 
    int id;  // not shared - each object has it's own 

    foo() 
    { 
     cnt++;  // update the counter of alive foos 
     id = nextid++; // assign an id 
     cout << "foo # " << id << " is alive " << endl; 
    } 

    ~foo() 
    { 
     cnt--; 
     cout << "foo # " << id << " is dead " << endl; 
    } 

    void stats() 
    { 
     cout << "I am foo number " << id << endl; 
     gstats(); 
    } 

    static void gstats() 
    { 
     cout << "Objects currently alive: " << cnt << endl; 
     cout << "Total number ever created: " << nextid << endl; 
    } 

    foo(foo &f) 
    { 
     cnt++;  // update the counter of alive foos 
     id = nextid++; // assign an id 
     cout << "foo # " << id << " is alive and copied from " << f.id << endl; 
    }  
}; 

int foo::cnt = 0; 
int foo::nextid = 0; 

void dmy1(foo a) 
{ 
    cout << "called dmy1 (by value) id is " << a.id << endl; 
} 


void dmy2(foo &a) 
{ 
    cout << "called dmy2 (by reference) id is " << a.id << endl; 
} 

int main(void) 
{ 
    foo::gstats(); 

    foo f1, f2; 
    f1.stats(); 

    dmy1(f2); 

    foo::gstats(); 
} 

Dies ist der Code, den mein Professor mir gegeben hat, um C++ statischen Code zu üben.Wie wird diese Funktion aufgerufen, wenn ich dieses C++ - Programm ausführe?

Aber wenn ich dieses Programm ausführen, habe ich eine Frage.

Objekte zur Zeit lebendig: 0

Total number ever created: 0 
foo # 0 is alive 
foo # 1 is alive 
I am foo number 0 
Objects currently alive: 2 
Total number ever created: 2 
foo # 2 is alive and copied from 1 
called dmy1 (by value) id is 2 
foo # 2 is dead 
Objects currently alive: 2 
Total number ever created: 3 
foo # 1 is dead 
foo # 0 is dead 

Dies ist die Ausgabe. Aber ich weiß nicht, warum diese Funktion genannt wird Könnten Sie erklären?

foo(foo &f) 
{ 
    cnt++;  // update the counter of alive foos 
    id = nextid++; // assign an id 
    cout << "foo # " << id << " is alive and copied from " << f.id << endl; 
} 

Und auch, warum static void gstats() {~} nach zerstörend foo # 2 genannt wird?

+4

Es ist eine Kopie Konstruktor aufgerufen wird. Ihr Prof sollte wahrscheinlich mehr Zeit auf die Grundlagen verwendet haben, bevor Sie solchen unordentlichen Code auf Sie fallen lassen. – StoryTeller

Antwort

1

Ok nennen, versuche ich zu erklären, was

Zuerst geschieht es zeigte keine Objekte zu diesem Zeitpunkt existieren

foo::gstats(); 

Jetzt f1 und f2 deklariert und auf dem Stapel erstellt (2 Objekte lebendig)

foo f1, f2; 

f1.stats wird aufgerufen und zeigt den aktuellen Stand

f1.stats(); 

f2 wird durch Wert (copyed auf Stapel mit Kopie Konstruktoraufruf foo(foo &f)) DMY1 (3 Objekte lebendig)

dmy1(f2); 

nach dem Verlassen vergangen DMY1 es Umfang (von ihrer benutzten Stack-Variablen) ist zerstört und f2 Kopie wird es destructor (2 Objekte lebendig) genannt ist und dieser Status wird angezeigt

foo::gstats(); 

Dann main() gelassen wird und es ist Umfang zerstört wird, wie gut und f1 und f2 Destruktoren werden aufgerufen (0 Objekte am Leben)

+0

Was für eine gute Antwort – KKEUN

1

Die Funktion heißt copy constructor. Es heißt, weil Sie das Objekt f2 an Wert dmy1 übergeben und eine Kopie des Objekts erstellt wird. Wenn Sie das Objekt a innerhalb von dmy1 ändern würden, würde f2 gleich bleiben - weil Sie implizit eine Kopie erstellt haben, als Sie den Parameter als Wert übergeben haben.

foo#2 wird zerstört, wenn Sie die Funktion dmy1, beenden, da sie nur innerhalb dieser Funktion aktiv ist. So ist es zerstört, bevor gstats.

-1

Es ist Kopie Konstruktor, wie es gesagt wurde. Aber Copy-Konstruktor sollte wie folgt erklärt wurden:

foo (const foo & f) { ... }

+0

Es ist üblich, dass ein Kopierkonstruktor eine 'const'-Referenz akzeptiert. Es gibt jedoch Fälle, in denen es angebracht ist, dass der Verweis nicht "const" ist. – Peter

+0

Können Sie sagen, wo es angebracht ist, ohne const zu deklarieren? Ich dachte, Konstruktor sollte immer neues Objekt initialisieren, ohne andere zu ändern. – bonczi

+0

Vor C++ 11 war es ein Hauptmittel zur Implementierung der Transfersemantik - zum Beispiel tat das (jetzt entfernte) 'std :: auto_ptr' genau das. Die Move-Semantik (eingeführt in C++ 11) bietet eine Alternative, aber es gibt Projekte, bei denen der Wechsel zu C++ 11 nicht erlaubt ist (ja, sie existieren, obwohl die Constraints oft nicht-technisch sind) eine Nicht-Const Copy Constructor ist die praktische Alternative. – Peter

Verwandte Themen