mikrocontroller.net

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


Autor: Schoasch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: BT (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Schoasch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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/EINF...

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

Autor: Ralf W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Schoasch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
var = 0;

Das geht natürlich nur in Methoden Deiner Klasse.

Autor: Schoasch (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

//**************************************************************
// Die Klassendefinition. Kommt normalerweise in ein Headerfile

class A
{
  public:
    A();    // diese Klasse hat einen Konstruktor
    ~A();   // diese Klasse hat auch einen Destruktor

    int foo();    // und in dieser Klasse gibt es eine Funktion
                  // namens foo. Von C her kennst du das schon:
                  // das ist ein ganz normaler Funktionsprototyp

  private:   // in dieser Klasse gibt es auch Dinge, die von aussen
             // nicht sichtbar sein sollen. Die quasi einem Objekt
             // vom Typ A ganz alleine gehören und die niemanden
             // sonst was angehen

    int m_Var;   // zb. diese Variable hier
};

//****************************************************************
// und hier die Implementierung der oben definierten Klasse
// die Implementierung findet sich normalerweise in einem
// eigenen *.cpp File

// zunächst der Konstruktor
A::A()
{
  // Aufgabe des Konstruktors ist es, ein Objekt dieser
  // Klasse in einen definierten Zustand zu bringen.
  // Für uns mag das zb. bedeuten, dass die Klassenvariable
  // m_Var den Wert 5 haben soll.

  m_Var = 5;

  // sobald also ein Objekt vom Typ A 'zur Welt kommt', wird der
  // Konstruktor aufgerufen und dieser setzt die Variable m__Var
  // auf 5
}

// Hier ist der Destruktor
// er wird aufgerufen, wenn ein Objekt 'stirbt'
// Hier haben wir nichts zu tun und eigentlich sollte man
// dann keinen Destruktor vereinbaren, aber was solls:
A::~A()
{
}

// und jetzt die Funktion foo
// da foo ja Mitglied der Klasse ist, hat sie selbstverständlich
// auf alle Funktionen und Variablen innerhalb dieser Klasse Zugriff
int A::foo()
{
  return m_Var;
}


//****************************************************
// Jetzt muss diese Klasse nur noch verwendet werden

int main()
{
  A DasObjekt;   // Eine Variable namens 'DasObjekt' wird
                 // definiert. Es ist vom Typ A
                 // Achtung: Da hier ein Objekt vom Typ A 'zur
                 // Welt kommt', wird sofort nachdem der Speicher
                 // dafür reserviert ist,der Konstruktor für das
                 // Objekt aufgerufen. WIr wir wissen, setzt der
                 // die Membervariable A::m_Var auf 5

                 // Das heist, hier an dieser Stelle, ist der
                 // Konstruktor bereits durch und A::m_Var enthält
                 // bereits einen vernünftigen Wert. Wir können nicht
                 // darauf zugreifen, weil A::m_Var ja private
                 // definiert ist (und das soll auch so sein)
                 // aber, wenn wir die Funktion foo aufrufen, so
                 // liefert die die 5 zurück

                 // rufe für das Objekt DasObjekt die Funktion
                 // foo auf
  int j = DasObjekt.foo();

  // j enthält jetzt den Wert den die Funktion DasObjekt.foo
  // zurückliefert. Das ist 5

  A NochEinObjekt;  // Noch ein Objekt vom Typ A wird definiert
                    // Auch für dieses Objekt wird jetzt in diesem
                    // Moment der Konstruktor aufgerufen, welcher
                    // NochEinObjekt::m_Var auf 5 setzt.

                    // Achtung: Beide Objekte, DasObjekt und
                    // NochEinObjekt verfügen beide jeweils über
                    // eine eigene Member-Variable m_Var. Die
                    // eine hat mit der anderen nicht das geringste
                    // zu tun. 

}  // Hier, mit der schliessenden Klammer, ist der Block zuende
   // der den Lebensbereich der beiden A Objekte darstellt. D.h.
   // die beiden A Objekte sterben hier. Als Konsequenz daraus
   // wird für beide Objekte jeweils der Destruktor aufgerufen


  

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Schoasch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.
int main()
{
  Integrator Integrierer;
  Differentiator Differenzierer;
  double Signal;

  while( std::cin >> Signal ) {
    Integrierer.AddSample( Signal );
    Differenzierer.AddSample( Signal );

    std::cout << "Differenzierer jetzt " << Differenzierer.Value() << "\n";
    std::cout << "Integrierer jetzt    " << Integrierer.Value() << std::endl;
  }

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.

Autor: Schoasch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Hermann (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht 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:

class Baustein
{
  public:
    virtual ~Baustein() {};

    virtual const char* Type() { return "unbekannt"; }
    virtual void Input( double Value ) = 0;
    virtual double Output() = 0;
};

class Integrator: public Baustein
{
  public:
    Integrator() : m_Sum( 0.0 ) {}

    virtual const char* Type()         { return "Integrator"; }
    virtual void Input( double Value ) { m_Sum += Value; }
    virtual double Output              { return m_Sum; }

  private:
    double m_Sum;
};

class Differentiator : public Baustein
{
  public:
    Differentiator() : m_Last( 0.0 ), m_Diff( 0.0 ) {}

    virtual const char* Type()         { return "Differentiator "; }
    virtual void Input( double Value ) { m_Diff = Value - m_Last;
                                         m_Last = Value; }
    virtual double Output()            { return m_Diff; }

  private:
    double m_Last;
    double m_Diff;
};

int main()
{
  double Signal;
  Baustein* Elems[2];   // Die 'Simulation' kann jetzt grade
                        // mal 2 Bausteine halten

  Elems[0] = new Integrator;
  Elems[1] = new Differentiator;

  while( std::cin >> Signal ) {
    
    for( int i = 0; i < 2; ++i ) {
      Elems[i]->Input( Signal );
      std::cout << Elems[i]->Type() << " jetzt "
                << Elems.Output() << std::endl;
    }
  }

  delete Elems[0];
  delete Elems[1];
}


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.

Autor: Schoaschi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
Tempvalue = Elems[i]->Output();
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

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Schoaschi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Schoaschi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.