Forum: PC-Programmierung C++;Aufbau und Struktur eines Programmes; Klassen usw


von Schoasch (Gast)


Lesenswert?

Hi

Ich bin jetzt zwangsbeglückt worden und muss C++ lernen.Ansich sollte es 
ja nicht so schwer sein, jedoch habe ich die Struktur bzw den Aufbau 
dahinter noch nicht so ganz verstanden.

Was das Programm machen soll:
Es soll eine Zahlenfolge über die Konsole einlesen und danach mit den 
Werte dann einmal integrieren und differenzieren (auf eine ganz panale 
art und weise).

In C wär das ganze für mich überhaupt kein Problem. Jedoch muss ich es 
mit C++ machen und das ganze eben Objektorientiert. Ich habe mir jetzt 
auch das Skript noch einmal zu gemüte geführt. Jedoch jedesmal wenn ich 
glaube, es verstanden zu haben, erkenne ich im nächsten Schritt,dass ich 
es nicht verstanden habe.
Nun wollte ich euch fragen, ob ihr mich etwas aufklären wie der 
Zusammenhang von Klasse, Funktion usw ist.
Also Konkret wie das ganze in meinem Fall aussehen würde. Also wie ich 
die einzelnen Funktionen zu Berechnung schreibe, ist mir kein Rätsel. 
Was mir nur etwas schleierhaft ist, wie Funktionen und Klassen 
interagieren und wie ich nun von einem Eingegebnen Wert in die Klasse 
komme und von dort in die Funktion. Weiters verstehe ich den Zugriff auf 
eine Klasse nicht so ganz.

Ich hoffe ihr könnt mir etwas weiterhelfen.

mfg Schoasch

von BT (Gast)


Lesenswert?

hm,

alos erst mal macht OO nur dann richtig sinn wenn du etwas programmieren 
sollst/willst was einen bestimmten realitätsausschnitt bzw "reales" 
system darstellt zum beispiel eine alarmanlage oder eine heizung welches 
aus gegenständen/dingen (objekten) besteht die zusammen agieren um 
irgendeine systemleistung zu erbringen. Nur einen Algorithmus kann man 
nicht wirklich objektorientiert abbilden das ist quark mit soße.

das was du dann tun musst ist das reale system so zu strukturieren wie 
es in der realiät auch aufgebaut ist aus objekten welche über 
eigenschaften (attribute) und verhalten verfügen (methoden) ...

hast du eine textuelle beschreibung der aufgabe?

cu BT

von Schoasch (Gast)


Lesenswert?

Hi

Die Sinnhaftigkeit dieser Aufgabe sei einmal in den Raum gestellt. Aber 
irgendwie müssen wir auch einmal mit OO anfagen.

Hier ist die Angabe: 
http://courses.mbi.tugraz.at/EINF-WS2006-2007/EINFUebung01.pdf

Ich bin jetzt immerhin schon so weit, dass ich von einer Funktion, die 
in einer Klasse ist, einen Returnwert bekomme.

Hast du einen Tipp für mich, wie ich am besten eine Variable 
initialisiere, damit sie drotzdem privat ist und nur beim 1. Mal mit 0 
initialisiert ist?

mfg Schoasch

von Ralf W. (Gast)


Lesenswert?

Hallo,

habe hier ein Buch gefunden welches zum Verständniss der OO vielleicht 
weiterhilft.

http://www.galileocomputing.de/openbook/oo/index.htm

Die Variable musst du als privat deklarieren und im Konstruktor der 
Klasse mit 0 initialisieren.
Wie die Syntax in C++ ist kann ich dir leider nicht verraten.

gruss ralf

von Schoasch (Gast)


Lesenswert?

Danke für den Link. Ich werde in mir das durchlesen.

>Die Variable musst du als privat deklarieren und im Konstruktor der
>Klasse mit 0 initialisieren.

Jetzt wärs halt noch interessant wie man darauf zugreifen kann ;-)
Aber irgendwie meckert der Compiler immer, wenn ich einen Konstruktor 
und Destruktor machen will.

von Frank (Gast)


Lesenswert?

1
var = 0;

Das geht natürlich nur in Methoden Deiner Klasse.

von Schoasch (Gast)


Lesenswert?

So. Schön langsam wirds.
Mein Fehler war, dass ich nur den Konstruktor erstellt habe und den 
destruktor nicht gemacht habe.

von Karl H. (kbuchegg)


Lesenswert?

Alle Variablen, die du innerhalb einer Klasse definierst,
sind Member dieser Klasse. Die Attributierung public, private,
protected regelt lediglich, wie von ausserhalb auf diese Member-
variablen zugegriffen werden kann.
1
//**************************************************************
2
// Die Klassendefinition. Kommt normalerweise in ein Headerfile
3
4
class A
5
{
6
  public:
7
    A();    // diese Klasse hat einen Konstruktor
8
    ~A();   // diese Klasse hat auch einen Destruktor
9
10
    int foo();    // und in dieser Klasse gibt es eine Funktion
11
                  // namens foo. Von C her kennst du das schon:
12
                  // das ist ein ganz normaler Funktionsprototyp
13
14
  private:   // in dieser Klasse gibt es auch Dinge, die von aussen
15
             // nicht sichtbar sein sollen. Die quasi einem Objekt
16
             // vom Typ A ganz alleine gehören und die niemanden
17
             // sonst was angehen
18
19
    int m_Var;   // zb. diese Variable hier
20
};
21
22
//****************************************************************
23
// und hier die Implementierung der oben definierten Klasse
24
// die Implementierung findet sich normalerweise in einem
25
// eigenen *.cpp File
26
27
// zunächst der Konstruktor
28
A::A()
29
{
30
  // Aufgabe des Konstruktors ist es, ein Objekt dieser
31
  // Klasse in einen definierten Zustand zu bringen.
32
  // Für uns mag das zb. bedeuten, dass die Klassenvariable
33
  // m_Var den Wert 5 haben soll.
34
35
  m_Var = 5;
36
37
  // sobald also ein Objekt vom Typ A 'zur Welt kommt', wird der
38
  // Konstruktor aufgerufen und dieser setzt die Variable m__Var
39
  // auf 5
40
}
41
42
// Hier ist der Destruktor
43
// er wird aufgerufen, wenn ein Objekt 'stirbt'
44
// Hier haben wir nichts zu tun und eigentlich sollte man
45
// dann keinen Destruktor vereinbaren, aber was solls:
46
A::~A()
47
{
48
}
49
50
// und jetzt die Funktion foo
51
// da foo ja Mitglied der Klasse ist, hat sie selbstverständlich
52
// auf alle Funktionen und Variablen innerhalb dieser Klasse Zugriff
53
int A::foo()
54
{
55
  return m_Var;
56
}
57
58
59
//****************************************************
60
// Jetzt muss diese Klasse nur noch verwendet werden
61
62
int main()
63
{
64
  A DasObjekt;   // Eine Variable namens 'DasObjekt' wird
65
                 // definiert. Es ist vom Typ A
66
                 // Achtung: Da hier ein Objekt vom Typ A 'zur
67
                 // Welt kommt', wird sofort nachdem der Speicher
68
                 // dafür reserviert ist,der Konstruktor für das
69
                 // Objekt aufgerufen. WIr wir wissen, setzt der
70
                 // die Membervariable A::m_Var auf 5
71
72
                 // Das heist, hier an dieser Stelle, ist der
73
                 // Konstruktor bereits durch und A::m_Var enthält
74
                 // bereits einen vernünftigen Wert. Wir können nicht
75
                 // darauf zugreifen, weil A::m_Var ja private
76
                 // definiert ist (und das soll auch so sein)
77
                 // aber, wenn wir die Funktion foo aufrufen, so
78
                 // liefert die die 5 zurück
79
80
                 // rufe für das Objekt DasObjekt die Funktion
81
                 // foo auf
82
  int j = DasObjekt.foo();
83
84
  // j enthält jetzt den Wert den die Funktion DasObjekt.foo
85
  // zurückliefert. Das ist 5
86
87
  A NochEinObjekt;  // Noch ein Objekt vom Typ A wird definiert
88
                    // Auch für dieses Objekt wird jetzt in diesem
89
                    // Moment der Konstruktor aufgerufen, welcher
90
                    // NochEinObjekt::m_Var auf 5 setzt.
91
92
                    // Achtung: Beide Objekte, DasObjekt und
93
                    // NochEinObjekt verfügen beide jeweils über
94
                    // eine eigene Member-Variable m_Var. Die
95
                    // eine hat mit der anderen nicht das geringste
96
                    // zu tun. 
97
98
}  // Hier, mit der schliessenden Klammer, ist der Block zuende
99
   // der den Lebensbereich der beiden A Objekte darstellt. D.h.
100
   // die beiden A Objekte sterben hier. Als Konsequenz daraus
101
   // wird für beide Objekte jeweils der Destruktor aufgerufen

  

von Rolf Magnus (Gast)


Lesenswert?

> Die Sinnhaftigkeit dieser Aufgabe sei einmal in den Raum gestellt. Aber
> irgendwie müssen wir auch einmal mit OO anfagen.

Irgendwie schon, aber dazu wäre eine Aufgabe, bei der OO wenigstens in 
irgendeiner Weise sinnvoll wäre, wesentlich besser geeignet.

> Hier ist die Angabe:
> http://courses.mbi.tugraz.at/EINF-WS2006-2007/EINF...

Ok. Viel mit OO ist da einfach nicht rauszuholen. Ich würde dafür 
eigentlich einfach nur vier Funktionen schreiben:

- Werte einlesen
- Differenzieren
- Integrieren
- Ausgeben

Sowas einfach in eine Klasse zu schreiben, geht zwar, hat aber nichts 
mit OO zu tun. Man könnte im Prinzip zwei Klassen "Differenzierer" und 
"Integrierer" schreiben und diese von einer gemeinsame Basisklasse 
ableiten, aber das bringt's nicht. Dafür ist die Aufgabe einfach zu 
klein.

von Karl H. (kbuchegg)


Lesenswert?

> Man könnte im Prinzip zwei Klassen "Differenzierer" und
> "Integrierer" schreiben

Ich denke so ist das auch gedacht:
Eine Klasse Integrator, eine Klasse Differentiator, davon
jeweils ein Objekt erzeugen und nacheinander Werte reinschaufeln.
Beide Objekte (Integrator, Differentiator) sollen natürlich
auch Auskunft über ihren jeweilgen Zustand (sprich den
integrierten, bzw. differentierten Wert) geben können.

Nimm als Motivation einfach ein Signal-Simulationsprogramm
an. 2 Elemente in diesem Baukasten sind Integrator, Differentiator.
Ein richtiges Simulationsprogramm müsste solche Objekte zur
Laufzeit noch miteinander verbinden können, bzw. beliebig
viele derartige Objekte erzeugen und verwalten können. Aber
hey! Irgendwo muss jeder mal wo anfangen.

von Schoasch (Gast)


Lesenswert?

@Karl Heinz Buchegger: Besten dank für diese informative Erklärung. Das 
hat jetzt einiges an Ordnung in mein C++-Wissen gebracht.

>Man könnte im Prinzip zwei Klassen "Differenzierer" und
>"Integrierer" schreiben und diese von einer gemeinsame Basisklasse
>ableiten, aber das bringt's nicht. Dafür ist die Aufgabe einfach zu
>klein.

Naja... Ich glaube wir sollte das eh mit Basisklasse und abgeleiteten 
Klassen machen, aber das kann ich noch nicht. Zuerst mach ich es einmal 
so.

Ich finde das Beispiel auch ziemlich unpassend und vorallem uneffektiv. 
In C wäre das ganze Programm glaube ich nur halb so gross und auch viel 
übersichtlicher. Aber nunja... der Professor wills halt einmal so.

von Karl H. (kbuchegg)


Lesenswert?

Lies dir auch mal folgendes durch:
Beitrag "Re: Wie große Programme programmieren?"

> In C wäre das ganze Programm glaube ich nur halb so gross und auch viel
> übersichtlicher

Auf lange Sicht gesehen nicht. OO ist einfach nur eine Technik
die dir hilft, Struktur und damit Übersicht in ein Programm
zu kriegen.
1
int main()
2
{
3
  Integrator Integrierer;
4
  Differentiator Differenzierer;
5
  double Signal;
6
7
  while( std::cin >> Signal ) {
8
    Integrierer.AddSample( Signal );
9
    Differenzierer.AddSample( Signal );
10
11
    std::cout << "Differenzierer jetzt " << Differenzierer.Value() << "\n";
12
    std::cout << "Integrierer jetzt    " << Integrierer.Value() << std::endl;
13
  }

Dieses Hauptprogramm ist selbsterklärend. Da brauch ich keinen
Kommentar oder sonstwas, das mir erklärt was hier eigentlich
passiert.

Ich kann auch super leicht ablesen, dass sowohl Integrator als
auch Differentiator jeweils eine Methode AddSample bzw. Value
unterstützen. Ich brauch nicht mit irgendwelchen dubiosen
globalen Variablen jonglieren sondern alles ist dort wo
es hingehört: Sowohl Integrator als auch Differntiator enthalten
selbst alles was benötigt wird um jeweils neue Signalwerte
zu verarbeiten. Das Hauptprogramm muss sich nicht darum kümmern.
Alles was es tun muss ist, ein Objekt vom jeweiligen Typ anzulegen.
Durch das Objekt, kriegt das Hauptprogramm die komplette Maschinerie
die hinter dem Objekt steht, zur Verfügung gestellt.

von Schoasch (Gast)


Lesenswert?

Ich danke euch für eure Hilfe. Ich hab das Programm jetzt einmal 
funktionsfähig zusammengebracht. Jetzt ist nur mehr Kosmektik 
angesagt(Dialog mit Benutzer und Eingabefehlererkennung). Und ich 
glaube, dass ich es auch schön langsam kappiert habe wie das ganze so 
läuft.
Jetzt bin ich recht optimistisch, dass ich mich nicht ganz plamieren 
werden bei der der Prüfung gggg

mfg Schoasch

von Hermann (Gast)


Lesenswert?

Ich habe euren Thread angeregt mitverfolgt und würde gerne wissen, wie 
das Ganze nun aber mit abgeleiteten-Klassen aussehen würde, eben eine 
Basis und differenzierer und integrierer als Ableitungen davon. 
Inwieweit würde hier virtual zur Anwendung kommen, würde es überhaupt 
sinn machen um hier Polymorphismus(ich denke das ist der richtige 
Ausdruck) anzuwenden?
Wo liegen potentielle Tücken, auf was soll man achten?

von Karl heinz B. (kbucheg)


Lesenswert?

Ob Inheritance und Polymorphie hier Sinn machen würde, hängt von
der Anwendung ab, die ich schreibe.
In der vorgegebenen Aufgabenstellung macht es keinen Sinn.

Wenn ich aber eine andere Aufgabenstellung wähle, dann
macht das sehr wohl Sinn (Kurzbeschreibung):
Zu schreiben ist ein Simulationssystem, bei dem die Bausteine
zur Laufzeit aus einem Vorrat ausgewählt werden und interaktiv
miteinander vernüpft werden können.

In diesem Fall wird es irgendwo einen Container geben, der
alle in der konkreten Situation verbauten Bausteine halten
muss. Das geht in C++ nur dadurch, dass man einen Container
von Pointern hat. Und daraus folgt, dass sowohl Integrator
als auch Differentiator von einer gemeinsamen Basisklasse,
nennen wir sie mal Baustein, ableiten muss, damit der
Container lauter Pointer auf Baustein halten kann.

Da aber verarbeitende Funktionen aus dem Container wiederrum
nur Pointer auf Bausteine bekommen, muss die eigentliche
Funktionalität mittels polymorphem Verhalten angestossen
werden. Jeder 'Baustein' hat eine Funktion Input, mit
der man an den Eingang des Bausteins einen Wert anlegt
und hat zb. eine Funktion Output, die den Signalwert am
Ausgang wiedergibt. Die Anzeigeklasse, muss nun nicht
wissen, welchen Baustein sie konkret bearbeitet: Sie
lässt sich einfach vom Container einen Baustein-Pointer
nach dem anderen geben, ruft polymorph über den Pointer
die Output Funktion auf und schreibt den erhaltenen Wert
zb. neben die graphische Abbildung.

Konkret würde das zb. so aussehen:
1
class Baustein
2
{
3
  public:
4
    virtual ~Baustein() {};
5
6
    virtual const char* Type() { return "unbekannt"; }
7
    virtual void Input( double Value ) = 0;
8
    virtual double Output() = 0;
9
};
10
11
class Integrator: public Baustein
12
{
13
  public:
14
    Integrator() : m_Sum( 0.0 ) {}
15
16
    virtual const char* Type()         { return "Integrator"; }
17
    virtual void Input( double Value ) { m_Sum += Value; }
18
    virtual double Output              { return m_Sum; }
19
20
  private:
21
    double m_Sum;
22
};
23
24
class Differentiator : public Baustein
25
{
26
  public:
27
    Differentiator() : m_Last( 0.0 ), m_Diff( 0.0 ) {}
28
29
    virtual const char* Type()         { return "Differentiator "; }
30
    virtual void Input( double Value ) { m_Diff = Value - m_Last;
31
                                         m_Last = Value; }
32
    virtual double Output()            { return m_Diff; }
33
34
  private:
35
    double m_Last;
36
    double m_Diff;
37
};
38
39
int main()
40
{
41
  double Signal;
42
  Baustein* Elems[2];   // Die 'Simulation' kann jetzt grade
43
                        // mal 2 Bausteine halten
44
45
  Elems[0] = new Integrator;
46
  Elems[1] = new Differentiator;
47
48
  while( std::cin >> Signal ) {
49
    
50
    for( int i = 0; i < 2; ++i ) {
51
      Elems[i]->Input( Signal );
52
      std::cout << Elems[i]->Type() << " jetzt "
53
                << Elems.Output() << std::endl;
54
    }
55
  }
56
57
  delete Elems[0];
58
  delete Elems[1];
59
}

Man beachte, wie innerhalb der Schleife keinerlei Information
mehr benötigt wird, von welchem Typ den nun das Objekt ist,
mit dem gearbeitet wird. Wenn da jetzt ein zusätzlicher möglicher
Baustein, sagen wir mal ein Inverter in das System eingearbeitet
werden müsste, so ändert sich an der Schleife genau gar nichts:
Die zusätzliche Inverter Klasse wird als Klasse geschrieben wird
mit den notwendigen virtuellen Funktinen ausgestattet. Ok
Irgendwann muss natürlich mal ein Objekt davon erzeugt werden,
aber die Schleife, die die 'Simulation antreibt' ändert sich
überhaupt nicht.

von Schoaschi (Gast)


Lesenswert?

Hi

Ist zwar schon ein bisschen her, aber jetzt muss ich mich wiedermal mit 
diesem Programm beschäftigen.

Nur hab ich jetzt ein kleines Problem und ich kann es nicht so lösen wie 
ich glaube es zu Lösen können.

Und zwar gehts jetzt darum, dass ich jetzt das programm so machen muss, 
dass man diverse "Bausteine" hintereinander schalten kann.
Was mir nicht klar ist: Wie übergebe ich jetzt das Ergebnis auf das 
nächste Baustein?

Ich hab jetzt einmal folgendes probiert:
1
Tempvalue = Elems[i]->Output();
2
Elems[i+1]->Input( Tempvalue );
Nach meinem Verständniss sollte in Tempvalue der Ausgabewert stehen. Und 
diesen übergebe ich dann in das nächste Element. (Tempvalue ist als 
double deklariert.)
Aber wenn ich das programm Compiliere, kommt zwar kein fehler, aber nach 
der 1. Eingabe eines Wertes, beendet das Programm.

Was hat es denn da? Was mache ich falsch?

mfg Schoasch

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Es könnte beispielsweise sein, daß i + 1 so groß oder gar größer wird 
wie die Anzahl der Elemente des Arrays Elems. Als Arrayindex darf aber 
nur ein Wert zwischen 0 und Anzahl-der-Elemente-Minus-1 verwendet 
werden.

Daß Dein Programm sich beendet, wird daran liegen, daß durch den 
Arrayüberlauf irgendwo ins Nirvana gefasst wird.

Mal drwtsn32* aufgerufen? Mal das Programm im Debugger laufengelassen?


*) angenommen, daß Du Windows verwendest

von Schoaschi (Gast)


Lesenswert?

Aja.. ok stimmt. Da war ich etwas übermütig mit meinen Array-Elementen. 
:-)

Ok.. im Grunde würds ja funktionieren :-) Aber ich hab jetzt echt wo 
einen Wurm in meinen Array-Elementen drin, der mir gerade etwas zu kopfe 
steigt.

Ich hab das ganze nemlich jetzt auf eine dynamische Erweiterung 
umgebaut. Und dadurch hat sich das ganze etwas verkomplziert.

Was ist denn bitte : drwtsn32* ? Wie man dieser Frage wohl entnehmen 
kann, hab ich es nicht aufgerufen :-)

Und debuggen funktioniert derweilen auch noch nicht ganz, da ich nicht 
weis wie das in diesem Compiler funktioniert. Also "debugge" ich mit der 
Konsole momentan  8-)

mfg Schoasch

von Schoaschi (Gast)


Lesenswert?

So

Das ganze läuft jetzt. Es waren echt nur fehler mit dem Array. Jetzt hat 
das ganze auch noch einen Komperator verpasst bekommen.

DAnke für Hinweise.

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.