Forum: Mikrocontroller und Digitale Elektronik Static class members


von Hermann E. (hermann_e)


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.

von EAF (Gast)


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.

von N. M. (mani)


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.

von Hermann E. (hermann_e)


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;

    MyClass MyObject;
    MyObject.var = 10;

    MyClass::test = 2;  // ==> leads to error

    return 0;
}

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

Danke, Hermann

von EAF (Gast)


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?

von Hermann E. (hermann_e)


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).

: Bearbeitet durch User
von EAF (Gast)


Lesenswert?

Absurde Argumentation.

von Rolf M. (rmagnus)


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.

: Bearbeitet durch User
von Wilhelm M. (wimalopaan)


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.

von EAF (Gast)


Lesenswert?

Wilhelm M. schrieb:
> sinnvolle Muster
Ja!
Das Singleton Muster.
(Welches Kotzreiz verursacht)

von PittyJ (Gast)


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 vom Autor gelöscht.
von Wilhelm M. (wimalopaan)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.