2017-10-02 1 views
-5
#include <iostream> 

using namespace std; 

class Foo { 

    int i; 
    int * p = new int; 
    *p = 5; // This doesn't worl 
    // If I instead use int * p = new int(5); it works. 
}; 

Warum das? Ich sehe, dass dies nur innerhalb einer Klasse passiert, wenn ich den gleichen Code auf die Hauptfunktion schreibe, sollte es funktionieren.Kann keiner Variablen innerhalb einer Klasse einen Wert zuweisen

+1

Die Sache, die nicht funktioniert, ist keine gültige Syntax. –

+2

Weil solche Ausdrücke innerhalb einer Funktion sein müssen. –

+2

Einer ist die Initialisierung von 'p', ein anderer ist die Zuweisung zu' * p'. Nur die Initialisierung ist außerhalb des Blockumfangs erlaubt. – StoryTeller

Antwort

0

Diese Syntax ist ungültig. Sie können nicht einfach Code innerhalb einer Klassendefinition schreiben. Stattdessen können Sie eine Funktion und Ihren Code in es schreiben funktioniert:

class Foo { 
public: 
    void bar() { 
    int * p = new int; 
    *p = 5; 
    } 
}; 

int main(int argc, char ** argv) { 
    Foo f; 
    f.bar(); 
} 

Hinweis: Sie sollten Ihre Variable in einer einzigen Anweisung, wenn möglich zuzuteilen bevorzugen und initialisieren:

int *p = new int(5); 

Statt von:

+0

Dies ist nicht default-initialize 'p' ... –

+0

Ich versuchte, das Beispiel so nah wie möglich an der Frage zu halten. Warum stört es dich? –

+0

stört mich nicht :-) Aber im Falle von 'int * p = new int (5)' würde 'p' im Laufe der Objektkonstruktion initialisiert werden. In einigen Situationen, z.B. Bei der Standardinitialisierung eines Vektors von 'Foo'-Objekten ist es sehr unpraktisch, Methoden nach der Objekterstellung aufrufen zu müssen. –

2

Ich schreibe dies unter der Annahme, dass Sie ein Mitglied dynamisch zuweisen müssen, und Sie können nicht einfach übergeben Argumente, aus welchen Gründen auch immer (diese Klasse sollte neu gestaltet werden, aber es ist ein anderes Problem).

Um ein paar Aussagen als Teil einer Variablen in der Klassendefinition ausführen zu initialisieren, können Sie es in einem Lambda-wickeln, und sie rufen Sie sofort:

class Foo { 
    int i; 
    int * p = []() { 
     auto *ret = new int; 
     *ret = 5; 
     return ret; 
    }(); // <-- Invokes the lambda right away 
}; 

Nur Initialisierung bei Namespace und Klassenbereich erlaubt ist . Andere Anweisungen müssen im Blockbereich erscheinen, den das Lambda bereitstellt.

Aber es ist chaotisch, schlecht beraten, und Sie sollten es nicht tun, es sei denn, Sie müssen wirklich. Eine Konstruktordefinition wäre besser.

+0

Danke für deine Antwort StoryTeller. Aber ich bin neu in der Programmierung, was meinst du mit Lambda? – user45147

2

Eine Klassendefinition besteht aus ihren Memberdeklarationen (wenn die Klasse ein Member enthält). Sie dürfen keine Anweisungen außer Deklarationen in der Klassendefinition verwenden.

Diese Anweisung in der Klassendefinition

*p = 5; // This doesn't worl 

ist keine Erklärung. Statt dieser beiden Aussagen

int * p = new int; 
*p = 5; // This doesn't worl 

könnten Sie einfach Erklärung

int * p = new int(5); 

Achten Sie auf die Standard-Smart-Pointer std::unique_ptr schreiben, die anstelle des Rohzeiger in Ihrer Klassendefinition verwendet werden können. In diesem Fall wird der Speicher automatisch freigegeben, wenn das Objekt aufhört zu existieren. Zum Beispiel

std::unique_ptr<int> p{ new int(5) }; 
Verwandte Themen