Forum: PC-Programmierung Klasse global nutzen


von Name (Gast)


Lesenswert?

Hallo,

ich habe ein Projekt mit mehreren Files. Ich benötige außerdem eine 
Klasse von welcher ich die Memberfunktionen in all meinen .cpp Dateien 
nutzen kann.

Es sieht wie folgt aus:

Eine Klasse mit dem Namen meineklasse. Diese ist in der meineklasse.cpp 
und meineklasse.h

Nun erstelle ich in main.cpp in der Funktion main eine neue Klasse mit: 
meineklasse nummer1(123,123) und übergebe in den Konstruktor zwei 
Parameter.

Nun möchte ich aber die Memberfunktionen in der Datei nutzer.cpp 
benutzen.
z.B. nummer1.getData();
Jetzt sagt mir aber mein Compiler:  error: nummer1 was not declared in 
this scope.


Wie kann ich die Klasse nummer1 nun global nutzen? Hat jemand eine Idee?


Grüße

von Tom (Gast)


Lesenswert?

Gleich brüllt ein Experte Singleton. Das ist in 99% der Fälle der erste 
Schritt ins Verderben und geschminkter Spaghetti-Code.

Wenn es ohne globale Variablen (Singletons gehören dazu) geht, soll man 
es auch ohne erledigen. Das nervt vielleicht am Anfang, erhöht aber die 
Chancen, das Programm auch in ZUkunft überblicken und ändern zu können.

Meist der bessere Ansatz:
Wenn Dein Objekt nutzer einen Verweis auf ein Meineklasse-Objekt 
braucht, weil es darauf zugreifen muss, bekommt es eine Referenz darauf 
im Konstruktor übergeben. Das macht die Abhängigkeit explizit klar.

Wenn alle Objekte kreuz und quer auf alle anderen zugreifen, so dass 
diese Methode nicht praktikabel ist, ist der Aufbau des Programmes Mist 
und muss sowieso repariert werden.

main.cpp:
1
#include "nutzer.h"
2
#include "meineklasse.h"
3
4
int main()
5
{
6
    MeineKlasse nummer1(123, 456);
7
    Nutzer nu(nummer1);
8
    nu.doit();
9
}

meineklasse.h:
1
#pragma once
2
#include <iostream>
3
4
class MeineKlasse
5
{
6
public:
7
    MeineKlasse(int ia, int ib);
8
    void getData();
9
private:
10
    int a;
11
    int b;
12
};

meineklasse.cpp:
1
#include "meineklasse.h"
2
#include <iostream>
3
4
MeineKlasse::MeineKlasse(int ia, int ib): a(ia), b(ib)
5
{
6
}
7
8
void MeineKlasse::getData()
9
{
10
    std::cout << "MeineKlasse: " << a << "\t" << b << "\n";
11
}

nutzer.h:
1
#pragma once
2
#include "meineklasse.h"
3
4
class Nutzer
5
{
6
public:
7
    Nutzer(MeineKlasse& k);
8
    void doit();
9
private:
10
    MeineKlasse& blubb;
11
};

nutzer.cpp:
1
#include "nutzer.h"
2
#include <iostream>
3
4
Nutzer::Nutzer(MeineKlasse& k): blubb(k)
5
{
6
}
7
8
void Nutzer::doit()
9
{
10
    std::cout << "Nutzer.doit(): ";
11
    blubb.getData();
12
}

von Daniel A. (daniel-a)


Lesenswert?

Diese Frage ist viel zu unspezifisch. Es gibt verschiedene 
Designpatterns die in verschiedenen Situationen angewendet werden 
können.

Angenommen, es darf von der Klasse nur eine Instanz geben, dann gibt es 
das singleton pattern. Meistens bringt dieses jedoch mehr Probleme als 
nutzen.

Wenn das Objekt nicht von anderen Objekten abhängt, und für das gesammte 
program relevant ist, bieten sich globale variablen an. Dies kann z.B. 
für globale Konfigurationen nützlich sein. Man sollte aber möglichst 
wenig davon haben, da man immer auf diese verzichten kann. Der trick ist 
hier zu erkennen, was zu welcher Compilationsunit gehört und wieviel 
Kapselung man braucht.

Wenn es gleichzeitig mehrere Implementationen eines Objects gibt, und 
erst zur Runtime feststeht welche verwendet werden soll, bietet sich das 
Factory pattern & interfaces an. Hauffig ist das aber overkill und man 
benötigt sowiso nur eine davon, die man einfach direkt dazulinken 
könnte.

Das Beispiel von Tom ist eine form von Dependency Injection. Das ist 
haufig sinvoll, aber man sollte nicht zuviele davon in einer Klasse 
haben.

Welches entwurfsmuster auf deinen Anwendungsfall am besten passt musst 
du selbst herausfinden. Achte einfach darauf, dass der code sauber 
Strukturiert ist, aber halte ihn möglichst simpel.

von Name (Gast)


Lesenswert?

Vielleicht habe ich mich etwas unglücklich ausgedrückt ich versuche mal 
näher zu beschreiben was ich möchte. Danke trotzdem für die ersten 
Antworten.

Ich habe eine main.cpp
1
#include "nutzer.h"
2
#include "meineklasse.h"
3
4
int main()
5
{
6
    MeineKlasse nummer1(123, 456);
7
    nutzerfunktion(); //In dieser Funktion sollen nachher Daten der Klasse
8
                      // "nummer1" genutzt werden
9
    
10
}

nutzer.h
1
#ifndef NUTZER
2
#define NUTZER
3
void nutzerfunktion();
4
#endif

nutzer.cpp
1
nutzerfunktion()
2
{
3
int a;
4
5
//blabla ganz viel code...
6
7
//UND NUN!!
8
a=nummer1.getMeAPrivateInt(); //hier meckert jetzt der Compiler. Weil ihm die Klasse
9
                      //nummer1 nicht bekannt ist. 
10
11
}




Würde ich jetzt den call
1
MeineKlasse nummer1(123, 456);
 in die nutzer.cpp machen klappt alles, solange sich der Datenaustausch 
nur auf die nutzer.cpp beschränkt. Nur wie gesagt, ich möchte die 
erstellte Klasse global in meinem Programm nutzen können.

von Oliver S. (oliverso)


Lesenswert?

Dann musst du die auch global anlegen.

Allerdings gibt es seit ungefähr Anfang der Zeitrechnung in so ungefähr 
allen Programmiersprachen das Konzept der Parameter für Funktionen.

Also definier deine nutzerfuktion mit einem passenden 
Referenzparameter...

Oliver

: Bearbeitet durch User
von Daniel A. (daniel-a)


Lesenswert?

Name schrieb:
> Nur wie gesagt, ich möchte die
> erstellte Klasse global in meinem Programm nutzen können.

Kannst du doch schon. Oder mainst du die Klasseninstanz/das Objekt 
nummer1? Was hindert dich dann daran, dieses Global zu Definieren?
1
main.cpp
2
3
#include "globals.h"
4
#include "nutzer.h"
5
#include "meineklasse.h"
6
7
MeineKlasse nummer1(123, 456);
8
9
int main(){
10
    nutzerfunktion(); //In dieser Funktion sollen nachher Daten der Klasse
11
                      // "nummer1" genutzt werden
12
}
13
14
globals.h
15
16
extern MeineKlasse nummer1;
17
18
nutzer.h
19
20
#ifndef NUTZER
21
#define NUTZER
22
void nutzerfunktion();
23
#endif
24
25
nutzer.cpp
26
27
#include "globals.h"
28
#include "nutzer.h"
29
30
void nutzerfunktion(){
31
  int a;
32
33
  //blabla ganz viel code...
34
35
  //UND NUN!!
36
  a=nummer1.getMeAPrivateInt(); //hier meckert jetzt der Compiler. Weil ihm die Klasse
37
                      //nummer1 nicht bekannt ist. 
38
39
}

Ich glaube jedoch nicht, dass du weist, was du wirklich willst. 
Ausserdem solltest du mal den Warnlevel auf Maximum und einen Standard 
einstellen (unter gcc mit "-Wall -Wextra -pedantic -Werror"), das 
fehlende void vor nutzerfunktion ist grauenhafter style, ganz zu 
schweigen davon das nutzerfunktion weder eine Klasse noch einen 
Namespace hat.

Um noch zu zeigen was Oliver S. vorschlägt:
1
main.cpp
2
3
#include "nutzer.h"
4
#include "meineklasse.h"
5
6
int main(){
7
    MeineKlasse nummer1(123, 456);
8
    nutzerfunktion(nummer1); //In dieser Funktion sollen nachher Daten der Klasse
9
                      // "nummer1" genutzt werden
10
}
11
12
nutzer.h
13
14
#ifndef NUTZER
15
#define NUTZER
16
void nutzerfunktion(MeineKlasse&);
17
#endif
18
19
nutzer.cpp
20
21
#include "nutzer.h"
22
23
void nutzerfunktion(MeineKlasse& nummer1){
24
  int a;
25
26
  //blabla ganz viel code...
27
28
  //UND NUN!!
29
  a=nummer1.getMeAPrivateInt(); //hier meckert jetzt der Compiler. Weil ihm die Klasse
30
                      //nummer1 nicht bekannt ist. 
31
32
}

von nana (Gast)


Lesenswert?

Ich glaube hier ist der Spruch "Kauf dir ein (gutes) C++ Buch."* 
wirklich angebracht.

*Ein gutes C-Buch wuerde hier auch weiterhelfen um zu verstehen was man 
ueberhaupt tut.

von Name (Gast)


Lesenswert?

Daniel A. schrieb:
> Ich glaube jedoch nicht, dass du weist, was du wirklich willst.

Doch.

Daniel A. schrieb:
> Ausserdem solltest du mal den Warnlevel auf Maximum und einen Standard
> einstellen (unter gcc mit "-Wall -Wextra -pedantic -Werror"), das
> fehlende void vor nutzerfunktion ist grauenhafter style, ganz zu
> schweigen davon das nutzerfunktion weder eine Klasse noch einen
> Namespace hat.

Mein Code ist ja auch nur ein bsp. natürlich fehlen da noch tausend 
Dinge. Es ging hier nur darum mal schematisch darzustellen was mein 
Problem ist.

Es hilft auch nicht wenn ich den call:
1
MeineKlasse nummer1(123, 456);
 vor die "main" setze. So wie du es hier vorgeschlagen hast.
1
main.cpp
2
3
#include "globals.h"
4
#include "nutzer.h"
5
#include "meineklasse.h"
6
7
MeineKlasse nummer1(123, 456);
8
9
int main(){
10
    nutzerfunktion(); //In dieser Funktion sollen nachher Daten der Klasse
11
                      // "nummer1" genutzt werden
12
}

Mir geht es nur darum, dass mein Programm mittlerweile viele Dateien 
hat. Ich habe eine Klasse erstellt in welcher Kerninformationen von 
jedem Sensor gespeichert werden. Mit jedem:
1
MeineKlasse nummer1(123, 456);
1
MeineKlasse nummer2(123, 456);
1
MeineKlasse nummer3(123, 456);

Erzeuge ich einen Sensor. NUN möchte ich aber egal wo in meinem Programm 
die Möglichkeit haben diese Daten zu ändern. Dafür habe ich die 
Sensordaten private gesetzt und mir Funktionen geschrieben, mit denen 
ich diese nach Bedarf ändern kann.

von Name (Gast)


Lesenswert?

Alle anderen Funktionen wie z.B. die "nutzerfunktion" werden egal wo in 
meinem Programm, erkannt. Ich habe nur das problem mit der Klasse. Es 
ist mir irgendwo nicht möglich außerhalb der Main, memberfunktionen der 
Klasse zu nutzen. Ich kann diese NUR!!! da nutzen, wo ich auch 
tatsächlich den call:

main.cpp
...
...
1
MeineKlasse nummer1(123, 456);
...
...
gemacht habe.
Jetzt wäre es mir möglich in der main.cpp z.B. diese Funktion zu nutzen:

nummer1.gebeDenBlödenTextAus();

In jeder anderen Datei ist es mir aber nicht möglich nun diese Fkt. zu 
nutzen. Ich verstehe aber nicht warum. Mit normalen Funktionen geht es, 
sobald man den "header" anfügt. Mit der Klasse aber nicht.

von Ralf G. (ralg)


Lesenswert?

Name schrieb:
> In jeder anderen Datei ist es mir aber nicht möglich nun diese Fkt. zu
> nutzen. Ich verstehe aber nicht warum. Mit normalen Funktionen geht es,
> sobald man den "header" anfügt. Mit der Klasse aber nicht.

Die Klasse ist ja keine Funktion. Das ist eine Variable! Auf die 
könntest du auch nicht zugreifen. Außer: du gibst die bekannt... (Ich 
schreibe jetzt mal nicht, dass man dazu 'extern' verwendet.)

von Random .. (thorstendb) Benutzerseite


Lesenswert?

static functions oder Pointer auf Objekt (die Klasse) im Konstruktor 
durchreichen.
1
Foo::Func(bar);

von Name (Gast)


Lesenswert?

Habe es nun hinbekommen.


Danke

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.