Static class members

OP #7327661
Lesenswert?

Guten Tag, nachdem ich mich mit folgendem Problem jetzt schon eine Weile herumschlage wollte ich endlich mal Klarheit schaffen. Offensichtlich habe ich noch Lücken in meinem "Class"-Verständnis die ich überwinden sollte.

Hier das Problem:

//================ Main (main.cpp) ============================ #include <stdio.h>

class MyClass { public: uint8_t var; static uint8_t test; };

int main() { uint8_t lala = 0; MyClass MyObject; MyObject.var = 10;
MyClass::test = 2; // ==> leads to error
return 0; }

//============================================================

Wenn ich die Zeile "MyClass::test = 2; " auskommentiere läuft alles wie gewünscht, im obigen Zustand krieg ich aber folgende Fehlermeldung: "Main.cpp:(.text.main+0x4): undefined reference to `MyClass::test'" Irgendwas läuft also wegen der "static"-Definition von "uint8_t test" schief. Als Compiler nutze ich avr-g++ in MPLAB (unter Ubuntu).

Hätte mir jemand ein Tip was ich da falsch mache bzw. wie ich statische Klassenvariable richtig definieren muß damit es klappt ?

Vielen Dank, Hermann

Ps: Aus Gründen die mir nicht klar sind wirbelt die Formatierung der Webseite mein Programm unansehnlich durcheinander, bitte dafür um Entschuldigung.

Gast #7327667
Lesenswert?

Wenn sich der Compiler über eine fehlender Definition beschwert, dann ist auch anzunehmen, dass diese benötigt wird.

1
class MyClass
2
{
3
 public:
4
  uint8_t var;
5
  static uint8_t test;
6
};
7

8
inline uint8_t MyClass::test; 
9

10
int main()
11
{
12
    uint8_t lala = 0;
13
    MyClass MyObject;
14
    MyObject.var = 10;
15
    MyClass::test = 2;  // ==> leads to error
16
    return 0;
17
}

ungetestet

Übrigens Statische Klassen Eigenschaften sind in der Regel böse.

#7327668
Lesenswert?

Hermann E. schrieb:

Hätte mir jemand ein Tip was ich da falsch mache bzw. wie ich statische Klassenvariable richtig definieren muß damit es klappt ?

https://www.geeksforgeeks.org/static-data-members-c/

1
The above program calls only Bs constructor, it doesnt call As constructor. The reason for this is simple, static members are only declared in a class declaration, not defined. They must be explicitly defined outside the class using the scope resolution operator.
OP #7327711
Lesenswert?

Supa !

War gerade Essen, so dass ich eure Beiträge nicht gleich gesehen habe. Die Sache mit dem "Inline" hat leider so nicht geklappt, mir war auch offen gestanden nicht ganz klar warum dies funktionieren sollte. Dennoch Danke für den Tip, ich schätze jede ernstgemeinte Hilfe auch wenn es nicht immer zum Ziel führt.

Letztlich war im von Mani vorgeschlagenen Artikel: https://www.geeksforgeeks.org/static-data-members-c/ der entscheidende Satz zu finden: "static members are only declared in a class declaration, not defined. They must be explicitly defined outside the class using the scope resolution operator."

Also:

#include <stdio.h>

class MyClass { public:

uint8_t var; static uint8_t test;

};

uint8_t MyClass::test;

int main() { uint8_t lala = 0;

1
MyClass MyObject;
2
MyObject.var = 10;
3
 
4
MyClass::test = 2;  // ==> leads to error
5

6
return 0;

}

mit der zusätzlichen (out of Scope) Zeile: "uint8_t MyClass::test;" lässt den Compiler fehlerfrei durchlaufen.

Danke, Hermann

Gast #7327735
Lesenswert?

Hermann E. schrieb:

Die Sache mit dem "Inline" hat leider so nicht geklappt,

Dann verwendest du eine veraltete C++ Variante. Und ja, in dem Beispiel macht das inline keinen Vorteil. Aber es ermöglicht die Unterbringung in *.h only Dateien, ohne weitere Klimmzüge.

Hermann E. schrieb:

mir war auch offen gestanden nicht ganz klar warum dies funktionieren sollte.

Wie wäre es mit einem schönen dicken und modernen C++ Grundlagenbuch?

OP #7327755
Lesenswert?

"Dann verwendest du eine veraltete C++ Variante."

Hatte mehrere Tage damit verwendet einen neueren Compiler zu installieren bin dann aber in andere Probleme geraten und irgendwann wird's dem Hobbyanwender(!) dann zu dumm...
Nur so: Ein menschliches Leben macht im Schnitt ca. 30kTage, ein Monat sind schon 1 Promille, da sollte man Prioritäten setzen.

"Wie wäre es mit einem schönen dicken und modernen C++ Grundlagenbuch?"

Grob abgeschätzt enthält ein "dickes und modernes C++ Grundlagenbuch" so ca. 10000 Informationselemente die man wissen müsste um C(++) perfekt (?) zu beherrschen.

Auch wenn Du nur eines davon entgangen ist, kann es früher oder später dazu führen, dass Du dir genau daran die Nase blutig stösst. Dann gibt es zwei Möglichkeiten: Entweder man liest das "dicke und moderne C++ Grundlagenbuch" noch einmal oder... Jedenfalls: Bevor ich meine Frage gepostet hatte, waren schon mehrere Stunden in ehrlicher Suche nach (m)einer Lösung flöten gegangen.

Ich spreche mehrere Fremdsprachen, aber ich wäre wohl nie weit gekommen, wenn ich mir vorgenommen hätte, eine neue Sprache erst dann zu verwenden, wenn ich sie perfekt beherrsche (also nie).

#7328052
Lesenswert?

Hermann E. schrieb:

Ich spreche mehrere Fremdsprachen, aber ich wäre wohl nie weit gekommen, wenn ich mir vorgenommen hätte, eine neue Sprache erst dann zu verwenden, wenn ich sie perfekt beherrsche (also nie).

Du musstest sie aber trotzdem lernen. Das muss man auch mit Programmiersprachen tun, wenn man halbwegs ernsthaft etwas damit tun möchte. Wobei bei Programmiersprachen zu beachten ist, dass es extrem mühsam ist, sie nur per trial&error und Nachfragen in Foren zu erlernen. Man braucht ohne entsprechende Literatur nicht weniger, sondern mehr Lebenszeit, um die Sprache gewinnbringend einsetzen zu können. Und da spreche ich aus eigener Erfahrung.

Hermann E. schrieb:

Jedenfalls: Bevor ich meine Frage gepostet hatte, waren schon mehrere Stunden in ehrlicher Suche nach (m)einer Lösung flöten gegangen.

Genau das meine ich damit. Das Problem, mit dem du dich jetzt mehrere Stunden herumgeschlagen hast, ist ein sehr grundlegendes Thema.

#7328101
Lesenswert?

EAF schrieb:

Wenn sich der Compiler über eine fehlender Definition beschwert, dann ist auch anzunehmen, dass diese benötigt wird.

1
> class MyClass
2
> {
3
>  public:
4
>   uint8_t var;
5
>   static uint8_t test;
6
> };
7
> 
8
> inline uint8_t MyClass::test;
9
> 
10
> int main()
11
> {
12
>     uint8_t lala = 0;
13
>     MyClass MyObject;
14
>     MyObject.var = 10;
15
>     MyClass::test = 2;  // ==> leads to error
16
>     return 0;
17
> }
18
>

ungetestet

In der Tat. So geht es:

1
class MyClass
2
{
3
 public:
4
  uint8_t var{0};
5
  inline static uint8_t test{0};
6
};

Man muss dann aber auch den C++-Standard entsprechend setzen und ein nicht gar so grottenalten Compiler benutzen.

Übrigens Statische Klassen Eigenschaften sind in der Regel böse.

Nein. Es gibt sogar sinnvolle Muster damit.

Gast #7328345
Lesenswert?

Ich programmiere jetzt 25 Jahre mit C++. Aber manche Feinheiten und Neuerungen bekommt man trotzdem nicht mit, und muss selber noch mal nachlesen. Von daher finde ich es legitim, wenn ein Hobbyist spezielle Sachen noch einmal nachfragt. Und die Änderungen gerade in dem Bereich zeigen, dass ältere Versionen nicht unbedingt konsistent und verständlich waren.

Beitrag #7328354 wurde von einem Moderator gelöscht.
#7328410
Lesenswert?

EAF schrieb:

Wilhelm M. schrieb:

sinnvolle Muster

Ja! Das Singleton Muster.

Nun, ein Singleton ist ein Beispiel von vielen dafür, bspw. um einen globalen Zustand zu kapseln...

(Welches Kotzreiz verursacht)

... daher sollte es (richtig angewendet) auch nicht zu Unwohlsein führen. An vielen Stellen wird auch ein Monostate dafür eingesetzt. Beide tun im Prinzip dasselbe (einen globalen Zustand kapseln): das Singleton ist eher ein strukturelles Muster während das Monostate ein Verhaltensmuster ist.

Gerade im µC Bereich gibt es zudem sehr sinnvolle Anwendungen von all-static templates/Klassen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren