Kann eine C++-Klasse sich selbst als Mitglied aufnehmen?
Lesezeit: 4 Minuten
Peter Steward
Ich versuche, eine Python-Routine zu beschleunigen, indem ich sie in C++ schreibe und sie dann mit ctypes oder cython verwende.
Ich bin ganz neu in c++. Ich verwende Microsoft Visual C++ Express, da es kostenlos ist.
Ich plane, einen Ausdrucksbaum und eine Methode zu implementieren, um ihn in Postfix-Reihenfolge auszuwerten.
Das Problem, auf das ich sofort stoße, ist:
class Node {
char *cargo;
Node left;
Node right;
};
Ich kann nicht deklarieren left oder right als Node Typen.
“Ich kann links oder rechts nicht als Knotentypen deklarieren.” Dies sollte eine Erklärung enthalten, warum, mit wörtlichen Zitaten aller erhaltenen Fehler. Vermutlich hat sich Ihr Compiler über etwas wie beschwert Node zu diesem Zeitpunkt ein unvollständiger Typ zu sein.
– Unterstrich_d
21. November 2019 um 13:34 Uhr
Nein, denn das Objekt wäre unendlich groß (weil jede Node hat als Mitglieder zwei andere Node Objekte, die jeweils zwei andere als Mitglieder haben Node Objekte, die jeder … na ja, Sie verstehen schon).
Sie können jedoch einen Zeiger auf den Klassentyp als Mitgliedsvariable haben:
class Node {
char *cargo;
Node* left; // I'm not a Node; I'm just a pointer to a Node
Node* right; // Same here
};
In diesem Fall ist ein bloßer Zeiger die richtige und intuitive Wahl. Es ist erwähnenswert, dass es andere Möglichkeiten sein kann, mich als Mitglied zu halten, wie zum Beispiel: reference, std::unique_ptr, std::shared_ptr oder std::weak_ptrsiehe auch: stackoverflow.com/questions/63365537/c-instance-of-same-class/…
– Amir Kirsch
12. August 2020 um 9:15 Uhr
Beachten Sie nur der Vollständigkeit halber, dass eine Klasse eine statische Instanz von sich selbst enthalten kann:
class A
{
static A a;
};
Dies liegt daran, dass statische Member nicht wirklich in den Klasseninstanzen gespeichert werden, sodass es keine Rekursion gibt.
Das hat mich ein wenig auf den Kopf gestellt, also würde ich etwas hinzufügen: In diesem Fall speichert jede Instanz der Klasse ‘A’ nur einen Zeiger auf einen Platz, der im statischen Speicher für die bestimmte Instanz ‘a’ zugewiesen ist. Die ‘a’-Instanz hat also auch einen Zeiger, der unendlich auf sich selbst zeigt: A* someA = new A;someA->.a.a.a...etc. (vorausgesetzt, ‘a’ ist ein öffentliches Attribut) und deshalb wird der Speicher endlich verwendet.
– gesungen
29. November 2017 um 13:45 Uhr
@hymced: Nein, keine der Instanzen von A enthält einen Zeiger, sicherlich nichts, das auf das statische Mitglied zeigt. -> und . erhalten Sie dieses Objekt dank Namenssuchregeln, nicht aufgrund eines Speicherlayouts.
– Leichtigkeitsrennen im Orbit
19. Juli 2019 um 16:08 Uhr
@Lightness-Races-in-Orbit Sie haben Recht, im obigen Beispiel gibt es keine Hinweise. Was ich meinte, ist, dass der verwendete Speicher endlich ist, nicht weil das statische Mitglied außerhalb der Klasseninstanz gespeichert wird, sondern weil dieses bestimmte statische Mitglied für jede Klasseninstanz gleich ist. Das liegt auch daran, dass die ´a´-Instanz nur sich selbst enthält und sonst nichts. Fügen Sie der Mischung ein einfaches (nicht statisches) int-Member hinzu, Sie haben selbst mit einem statischen Klassenmitglied nicht genügend Arbeitsspeicher.
– gesungen
20. Juli 2019 um 19:17 Uhr
@hymced Das stimmt einfach nicht. Warum denkst du das Hinzufügen eines Nicht-staticint Mitglied zu A würde dazu führen, dass dem Computer der Arbeitsspeicher ausgeht?
– Leichtigkeitsrennen im Orbit
20. Juli 2019 um 19:32 Uhr
Wieder habe ich mich geirrt: ‘A’ hätte ein int-Mitglied (nicht im statischen Speicher) anders als ‘a’ (im statischen Speicher), aber das int-Mitglied von ‘a’ wäre das gleiche wie ‘aa’ (da ‘ aa’ IST ‘a’), dasselbe wie ‘aaa’ usw. Der verwendete Speicher ist also endlich.
– gesungen
21. Juli 2019 um 20:21 Uhr
Nein, aber es kann eine Referenz oder einen Zeiger auf sich selbst haben:
class Node
{
Node *pnode;
Node &rnode;
};
Referenzen funktionieren in diesem Fall nicht wirklich, da sie nicht null sein dürfen und Sie Nullenden benötigen oder der Graph unendlich wäre.
– Blind
24. April 2010 um 21:17 Uhr
Sie könnten einen Dummy-Knoten erstellen, um das Tempo von NULL zu übernehmen. Dies funktioniert jedoch nicht gut, da Verweise nicht auf etwas anderes neu zugewiesen werden können und die Änderung eines Links die Rekonstruktion aller Knoten bis zur Wurzel erfordern würde.
– Kartoffelklatsche
24. April 2010 um 21:32 Uhr
@Blindy: Sie könnten auch die Knotenreferenz auf setzen *this statt NULL.
– MSalter
26. April 2010 um 12:38 Uhr
@Blindy, @All: Ja. Wie gesagt, ich bin ein echter Anfänger. Ich hatte eine sehr schwierige Zeit, dies zusammenzubringen.
– Peter Steward
26. April 2010 um 23:10 Uhr
@Blindy aber es gibt std::optional< std::reference_wrapper<Node> >! Lachen Sie nicht. Es ist einfacher zu werfen, wenn es ‘null’ ist, und weniger anfällig für versehentliche Zeigerarithmetik und dergleichen.
– Unterstrich_d
21. November 2019 um 13:32 Uhr
Amit G.
Verwenden Sie einen Zeiger, & besser initialisiert:
class Node {
char * cargo = nullptr;
Node * left = nullptr;
Node * right = nullptr;
};
Modernes C++
Es ist eine bessere Praxis zu verwenden Smart-Pointer (unique_ptr, shared_ptr, etc.), statt Speicherzuweisungen durch ‘new’:
#include <string>
#include <memory> // For 'std::unique_ptr'
class Node {
public:
std::string cargo;
std::unique_ptr<Node> left;
std::unique_ptr<Node> right;
};
int main()
{
auto bt = std::make_unique<Node>();
(*bt).cargo = "Coffee";
(*bt).left = std::make_unique<Node>();
}
9902100cookie-checkKann eine C++-Klasse sich selbst als Mitglied aufnehmen?yes
“Ich kann links oder rechts nicht als Knotentypen deklarieren.” Dies sollte eine Erklärung enthalten, warum, mit wörtlichen Zitaten aller erhaltenen Fehler. Vermutlich hat sich Ihr Compiler über etwas wie beschwert
Node
zu diesem Zeitpunkt ein unvollständiger Typ zu sein.– Unterstrich_d
21. November 2019 um 13:34 Uhr