Forum: PC-Programmierung CList in c++


von Sebastian U. (sulmer)


Lesenswert?

Hey,
ich schreibe gerade ein Programm zum Senden und Empfangen von Daten über 
USB.
Für das Senden werden die Daten in einen Frame verpackt:

Anzahl Bytes:        1  1      1      ?   1
                     : CODE SUBCODE DATEN ;

Nun soll es möglich sein mehrere Befehle Hintereinander zu verschicken. 
Dafür sollen die zu sendenen Befehle in einer Liste gespeichert (später 
soll diese Liste in einer Datei gespeichert werden).
Für einen Befehl erstell ich mir folgende struct.

struct befehl
{
 int code;
 int subcode;
 CString daten;
};

Die Liste soll nun diesen Typ verwalten. Dafür definiert ich sie wie 
folgt:

CList<befehl,befehl&> befehlliste;

Das ganze läuft als MDI Projekt, die struct hab ich in der 
CTestDoc-Klasse ganz unten hingeschrieben. Die Definition der Liste 
befindet sich in

BOOL CTestDoc::OnNewDocument()


Nun meine Frage zu struct in Visual C++, werden diese noch genutz? 
Normal würde man ja ne eigene Klasse erstellen, aber das lohnt sich doch 
net wirklcih.
Wieso geht das mit dem struct nicht? Bzw. ist an der Definition der 
Liste was falsch?

von Patrick (Gast)


Lesenswert?

Hallo Sebastian,

probier's mal mit CList<struct befehl, struct befehl&>...

Eine Struktur in C++ ist quasi wie ein Klasse, nur dass alle Member 
public sind.

Gruß

Patrick

von Karl H. (kbuchegg)


Lesenswert?

Sebastian Ulmer wrote:

> struct befehl
> {
>  int code;
>  int subcode;
>  CString daten;
> };
>
> Die Liste soll nun diesen Typ verwalten. Dafür definiert ich sie wie
> folgt:
>
> CList<befehl,befehl&> befehlliste;
>
> Das ganze läuft als MDI Projekt, die struct hab ich in der
> CTestDoc-Klasse ganz unten hingeschrieben. Die Definition der Liste
> befindet sich in
>
> BOOL CTestDoc::OnNewDocument()
>
>
> Nun meine Frage zu struct in Visual C++, werden diese noch genutz?

Sicher. Warum nicht.
Ist ein legales C++ Sprachmittel. Für Typen wie du sie hast,
also Container die im Wesentlichen eigentlich nur Daten halten
ohne irgendwelche große Intelligenz mitzubringen, sind sie nach
wie vor gut zu gebrauchen.

(PS: Wusstest du, dass auch structs Member Funktionen haben können?
Tatsächlich gibt es nur einen Unterschied zwischen struct und class:
In einer struct ist per default alles public. Ansonsten sind struct
und class absolut gleichwertig.)

> Normal würde man ja ne eigene Klasse erstellen, aber das lohnt sich doch
> net wirklcih.

Wieso nicht?
Bis auf das eine public ist doch alles gleich

class befehl
{
  public:
    int code;
    int subcode;
    CString daten;
};

= vollwertiger Ersatz für deine Struct.

> Wieso geht das mit dem struct nicht? Bzw. ist an der Definition der
> Liste was falsch?

Ne. Was soll daran falsch sein?
Bis zu diesen letzten 2 Sätzen hast du noch gar nicht erwähnt, dass
du ein Problem hast, bzw. wie sich das Problem manifestiert. Also:
Hast du eine Fehlermeldung oder dergleichen?

von Karl H. (kbuchegg)


Lesenswert?

Patrick wrote:
> Hallo Sebastian,
>
> probier's mal mit CList<struct befehl, struct befehl&>...
>

Macht keinen Unterschied.
Im Gegensatz zu C ist der Strukturname in C++ bereits ein eigener
Datentyp.

von Sebastian U. (sulmer)


Lesenswert?

Ich bekomm die Meldung das CList nicht deklariert wurde. Muss ich die 
Liste "befehlsliste" nochmal extra in der Header Datei deklarieren?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

CList ist eine MFC-Klasse. Verwendest Du die MFC?

von Sebastian U. (sulmer)


Lesenswert?

Yupp mach ich

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Ist in stdafx.h die Datei afxtempl.h eingebunden?

von Sebastian U. (sulmer)


Lesenswert?

ok hatte nen tipfehler, hab "aftempl.h" statt "afxtempl.h" included, 
komischer das er das include geschluckt hat
jetzt tut jedenfalls

von Sebastian U. (sulmer)


Lesenswert?

was ist eigetnlcih der unterschied zwischen

#include "afxtempl.h"
und
#include <afxtempl.h>

von Karl H. (kbuchegg)


Lesenswert?

Sebastian Ulmer wrote:
> was ist eigetnlcih der unterschied zwischen
>
> #include "afxtempl.h"
> und
> #include <afxtempl.h>

Unterschiedliche Suchpfade auf denen ein Include File gesucht wird.
Normalerweise wird <> für System-Includes verwendet, während ""
für Projektspezifische Includes benutzt wird.

von Sebastian U. (sulmer)


Lesenswert?

ok soweit funktioniert es, nur bisschen doof das ich die CList in der 
OnNewDocument deklariere.
Ich muss die ja nachher serialisieren, dafür sollte es wohl eine 
Membervariable sein.
Wenn ich nun aber die Deklaration als Membervariable reinmachen möchte, 
so meckert der Kompiler rum.

von Karl H. (kbuchegg)


Lesenswert?

Sebastian Ulmer wrote:

> so meckert der Kompiler rum.

Mitlerweile solltest du schon wissen, dass eine
Aussage "der Compiler meckert" so wenig hilfreich ist, wie
ein Kühlschrank im Iglu eines Eskimo.

Der Compiler gibt eine Fehlermeldung. Welche?

von Sebastian U. (sulmer)


Lesenswert?

Sry hatte mich verklickt und wollte den Beitrag dann nochmal ändern, 
aber das geht irgendwie nicht.

Also der Kompiler sag was wegen
'CList' : Fehlende Speicherklasse oder Typbezeichner

von Karl H. (kbuchegg)


Lesenswert?

Zeig mal das komplette Header File.

von Sebastian U. (sulmer)


Angehängte Dateien:

Lesenswert?

Ich habe es auch schon mit einer Beispiel Headerdatei in der CList 
verwendet wird verglichen, aber eigentlich ist nichts anderst

von Karl H. (kbuchegg)


Lesenswert?

Das ist soweit in Ordnung.

stdafx.h ist inkludiert?
afxtemp.h ist in der stdafx.h inkludiert?

Wenn alles nichts hilft: Hast du schon mal einen "Rebuild All"
probiert.
Wenn der auch nicht hilft: Händisch das Debug Verzeichnis löschen
und nochmal neu builden lassen.


PS: Wozu brauchst du eigentlich soviele unterschiedliche Documente.
Das ist schon etwas ungewöhnlich. Ich hatte zwar oft den Fall, daß
ich zu einem Dokument viele verschiedene Views brauchte. Aber
mehrere unteschiedliche Dokumenttypen in einem Programm, den
Fall hatte ich noch nie. Und ich benutze die MFC seit immerhin
15 Jahren. Das heist natürlich nicht, dass es den Fall nicht
gibt. Es mag schon Programme geben, die in ein und demselben
Programm gleichzeit Bilder bearbeiten und Böresnkurse aus dem
Web holen müssen, aber der Regelfall ist das nicht.

von Sebastian U. (sulmer)


Lesenswert?

Hatte den include nur in der cpp-Datei drin, dachte das reicht.

Naja viele Dokumente sind es net, nur 2.
Das eine Dient zum Verwalten von Befehlslisten, die über USB versendet 
werden. Und da es sich dabei oft um viele kurze Befehle handelt, soll 
man die Listen abspeichern und wieder neu laden können.
Das zweite Dokument dient zum Erstellen eines Testberichts aufgrund der 
Antworten die auf die Befehle über USB zurück kommen.

von Karl H. (kbuchegg)


Lesenswert?

Sebastian Ulmer wrote:
> Hatte den include nur in der cpp-Datei drin, dachte das reicht.
>
> Naja viele Dokumente sind es net, nur 2.
> Das eine Dient zum Verwalten von Befehlslisten, die über USB versendet
> werden. Und da es sich dabei oft um viele kurze Befehle handelt, soll
> man die Listen abspeichern und wieder neu laden können.
> Das zweite Dokument dient zum Erstellen eines Testberichts aufgrund der
> Antworten die auf die Befehle über USB zurück kommen.

Da würde ich mal eher sagen: Das ist ein Designfehler.

Mehrere Dokumenttypen benutzt man dann, wenn das Programm 2 radikal
verschiedene Funktionalitäten unterstützen muss und die Daten
von dem einen Dokument nichts mit den Daten des anderen
Dokuments zu tun haben. Wie im bereits angesprochenen Fall, dass
ein und dasselbe Programm sowohl als Bildbearbeitungssoftware
als auch als Web Server fungieren soll. Das eine hat mit dem
anderen nichts zu tun aber aus irgendwelchen unerfindlichen
Gründen möchte der Programmierer beide Funktionalitäten in
einem Programm haben.

Das ist aber in deinem Fall nicht so.
Du hast nur ein Dokument, wobei das Dokument verschiedene Daten
speichert. Auf der einen Seite die Befehlslisten. Auf der anderen
Seite die tatsächlich abgesendeten Befehle und die Antworten darauf.

Es spricht nichts dagegen sich jeweils eigene Klassen für
die Liste von möglichen Befehlen zu machen und eine zweite Klasse
die abgesendete Befehle und die Antworten darauf speichert.
Dann hält das Dokument diese beiden Container als Member und
verteilt die Aufträge entsprechend.
Aber 2 getrennte Dokumente dafür würde ich nicht machen. Schon
alleine aus dem Grund nicht, weil ja für das Versenden von Befehlen
wahrscheinlich auf die Befehlsliste zurückgegriffen werden soll.
Nur: Wie kommt den das 2. Dokument an diese Befehlsliste ran?
Gar nicht! Weil die Daten im 2.ten Dokument (aus gutem Grund) vom
1ten Dokument komplett abgeschottet sind.

von Sebastian U. (sulmer)


Lesenswert?

Klingt soweit ganz logisch. Dann werf ich das 2. Dokument wieder raus^^.
Naja mein erstes Projekt in Visual C++, da kommen sicher noch mehr 
Fehler.
Bin schon froh wenn das tut was es soll und ich mich wieder auf die 
Programmierung des Mikrocontollers an die die USB Befehle gehn widmen 
kann.

von Sebastian U. (sulmer)


Lesenswert?

Nun hab ich meine Liste, die ich mit Daten befüllen kann.
Diese soll in dem View als Tabelle mit 3 Spalten 
(Code,Subcode,Data)angezeigt werden.
Dazu verwende ich einen CListCtrl.
Befüllen tu ich die Liste am besten in der OnDraw-Methode der Viewklasse 
oder?

von Karl H. (kbuchegg)


Lesenswert?

Sebastian Ulmer wrote:
> Nun hab ich meine Liste, die ich mit Daten befüllen kann.
> Diese soll in dem View als Tabelle mit 3 Spalten
> (Code,Subcode,Data)angezeigt werden.
> Dazu verwende ich einen CListCtrl.
> Befüllen tu ich die Liste am besten in der OnDraw-Methode der Viewklasse
> oder?

Ja und nein.

Der prinzipielle Datenfluss sieht immer so aus:

Der Benutzer macht irgendeine Aktion an der Oberfläche.
Handelt es sich um eine Manipulation der Daten, dann geht
der Befehl an das Dokument. Das Dokument seinerseits macht die
Änderung entweder selbst oder beauftragt einen seiner Member
mit der Manipulation.

Ist die Datenänderung abgeschlossen, so wird im Dokument:
  * SetModifiedFlag( TRUE );
    aufgerufen, damit das Dokument als verändert markiert ist
    und die MFC beim Programmende nachfrägt, ob man nicht speichern
    möchte

  * UpdateAllViews aufgerufen

Der UpdateAllViews geht alle zum Dokument registrierten Views durch
und ruft bei jedem die Funktion OnUpdate auf. OnUpdate im View
seinerseits wertet die Übergebenen Parameter aus (auf die Art kann
man vom Dokument gezielt Befehle an jeden View durchbringen)
und behandelt diese. Die Default Aktion von OnUpdate ist es,
einen Invalidate() aufzurufen, der dafür sorgt, dass die OnDraw
Funktion des Views aufgerufen wird. Damit zeichnet sich jeder
View neu und zu diesem Behufe holt er sich vom Dokument die
neuesten Daten.

Man kann jetzt einige Punkte überspringen bzw. anpassen.
In deinem Fall wäre das sogar angebracht. Denn OnDraw soll ja
eigentlich nur das Fenster neu zeichnen. In deinem Fall hätte
das dann den Nachteil, dass die Liste jedesmal neu befüllt wird,
wenn zb das Fenster wieder in den Vordergrund geholt wird oder
ein Fenster welches das Programmfenster verdeckte geschlossen
wird. Das führt dann jedesmal zu einem kurzen Geflacker, wenn die
Liste neu aufgebaut wird.
Der Punkt ist der, dass das ListControl seinen OnDraw schon
ganz alleine richtig macht. Das Befüllen der Liste ist aber nur
dann notwendig, wenn sich die Daten auch tatsächlich ändern.
Und genau da ist dein Einstiegspunkt. Das Dokument kann dem View
gezielt mitteilen:
"Jetzt haben sich die Daten verändert".
Und zwar kann es das tun, indem es beim UpdateAllViews einen Code
für das Hint Argument mitgibt (den Code vergiebst du selber).
Die View sieht sich in ihrer eigenen OnUpdate Funktion diesen
Code an und entscheidet: Jetzt haben sich die Daten geändert, ich
muss das Control neu befüllen.

Um damit nochmal zur Frage zurückzukommen: Macht man das im OnDraw.
Ja: man kann es so machen und ist damit auf jeden Fall auf der
    sicheren Seite.
Nein: man wird sinnvollerweise nicht so machen, weil sonst die
    Liste bei jeder Fensteroperation flackern wird.

von Sebastian U. (sulmer)


Lesenswert?

Wie serialisier ich nun diese Liste? Ich hab ja die Funktion

void CSendeDoc::Serialize(CArchive& ar)
{
  if (ar.IsStoring())
  {
    // ZU ERLEDIGEN: Code zum Speichern hier einfügen
  }
  else
  {
    // ZU ERLEDIGEN: Code zum Laden hier einfügen
  }
}

vorgegeben.

Kann ich die komplette Liste serialisieren? Oder muss ich mir jeden 
einzelnen Knoten holen und dort die einzelnen Werte serialisieren?

von Karl H. (kbuchegg)


Lesenswert?


von Karl H. (kbuchegg)


Lesenswert?

Hier findet sich auch einiges zum Thema:
http://www.pluralsight.com/articlecontent/cpprep1295.htm

von Sebastian U. (sulmer)


Lesenswert?

Danke werd da gleich mal drüberlesen

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.