Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder einen alternativen Browser verwenden.
Ist ne *.ppt, also eine Powerpoint-Datei, zu öffnen mit Word oder LibreOffice.
Zum Zugriff: Für sowas kann man ein Objekt nutzen, dass auf alle Objekte zugreifen kann (also einen "Manager", der alle z.B. in einer Liste hat). Dann braucht jedes Objekt nur noch Zugriff auf diesen Mittelsmann. In deinem Fall könnten die Eingabefunktionen auch per return die eingelesenen Daten an die main-Funktion zurückgeben und die Ausgabefunktion dann mit den IPs aufgerufen werden. Gibt noch mehr Möglichkeiten, aber das wäre die "Anfängervariante".
P.S.: Man schreibt bei C++ eigentlich kein void als Übergabevariable bei Funktionen. Also entweder int/void GebeDaten(int daten1, float daten2); oder int/void NehmeDaten();
Datenbank
|
Manager
/ | \
A B C D (Clients)
A,B und C, wissen vom Manager, aber nichts voneinander? Zudem verwaltet der Manager quasi die Datenbank. D wird in der Managerliste nicht gelistet.
Meine Methode:
Datenbank
/ | \
A B C D
Daher direkter (mehr oder weniger) Zugang zur Datenbank und A,B und C stehen auch direkter miteinander, über die Datenbank in Kontakt. D hat keine Anbindung zur Datenbank.
1. Ist D wirklich so ahnungslos? Ich denke ja, weil D keinen Bezug zur Datenklasse hat, oder? Durch denn Entzug der Zuordnung, kann ich de fakto, nicht nur D denn Schlüssel entziehen, sondern das Schloss ist zugeschweisst.
2. A,B und C können so oder so nur die Daten aus der Datenklasse ziehen, wenn entsprechende Tunnel genutzt werden? Also in meinem Beispiel GetIP.
P.S.: Man schreibt bei C++ eigentlich kein void als Übergabevariable bei Funktionen. Also entweder int/void GebeDaten(int daten1, float daten2); oder int/void NehmeDaten();
So was wurmt mich auch immer. Diesen void func(void) Blödsinn gibt es nur aus Gründen der Rückwärtskompatibilität zu einem Steinzeitdialekt von C, in dem void func() hieß "Diese Funktion nimmt eine unbestimmte Anzahl von Parametern.", während void func(void) bedeutete "Diese Funktion nimmt keine Parameter.".
Aber sobald ein Programm irgend welche C++-Konstrukte enthält, ist es so wie so nicht mehr rückwärtskompatibel zu C, also kann man sich diesen Unsinn auch gleich sparen.
Zu denn Void. Ok, merk ich mir. Nur steht mir als Lehrmaterial nur das Internet zur Verfügung. Von daher wenn der Syntax so dasteht...
Ist sowieso so ein Ding. Zu C64 Zeiten hat ich zwei Handbücher mit einen kleinen Teil an Basic-Erläuterungen. Das war mein heiliger Gral, mein allwissende Datenbank. Zumal ich damals keinen Internetzugang hatte. Wer war ich? Universität?
Heute habe ich kein Buch, dafür das Internet. Zwei Milliarden Seiten, aber ich suche mir nach Lösungen immer noch einen Wolf. The internet is for... [bitte erst nach 21 Uhr vervollständigen]
Stopp, ihr meint bsp. int Daten::getsn(void), oder?
Ich bin nicht sicher, aber ich glaube aus Faulheit habe ich ausnahmsweise denn Wizard von VS genutzt. Ich glaube der hat das da eingehängt. Werde das mal entfernen und schauen ob sich der Compiler aufregt. Wenn ja, haben wir was zu lachen.
Ok, stört ihm nicht.
Datenbank
|
Manager
/ | \
A B C D (Clients)
A,B und C, wissen vom Manager, aber nichts voneinander? Zudem verwaltet der Manager quasi die Datenbank. D wird in der Managerliste nicht gelistet.
Meine Methode:
Datenbank
/ | \
A B C D
Daher direkter (mehr oder weniger) Zugang zur Datenbank und A,B und C stehen auch direkter miteinander, über die Datenbank in Kontakt. D hat keine Anbindung zur Datenbank.
1. Ist D wirklich so ahnungslos? Ich denke ja, weil D keinen Bezug zur Datenklasse hat, oder? Durch denn Entzug der Zuordnung, kann ich de fakto, nicht nur D denn Schlüssel entziehen, sondern das Schloss ist zugeschweisst.
2. A,B und C können so oder so nur die Daten aus der Datenklasse ziehen, wenn entsprechende Tunnel genutzt werden? Also in meinem Beispiel GetIP.
Zum ersten Beispiel: A,B,C können voneinander wissen. Du kannst natürlich jedem Objekt einen Verbindung zu allen anderen Objekten geben. Aber bei 1000 Objekten sind das 1000x999 Verknüpfungen=999000 Verknüpfungen. Bei 1000000 Objekten 999999000000 Verknüpfungen. usw usf. Das funktioniert also in der Praxis nicht.
Dazu kommt, das das Objekt "Datenbank" den Manager verwaltet, nicht andersrum.
Und wenn du nirgendwo eine Verbindung zu Objekt D hast, hast du ein Speicherleck geschaffen. Wenn nirgendwo im Code drauf zugegriffen werden kann, kann es weder benutzt, noch gelöscht werden. Und wenn du regelmäßig Objekte erzeugst, die nicht gelöscht werden können, steigt der Arbeitsspeicherbedarf stetig an, bis der RAM voll ist und das Programm abstürzt.
Dein System ohne Manager würde auch funktionieren. Die Objekte A,B,C bräuchten einen Rückbezug zur Datenbank und die Datenbank hat Verbindungen zu den Objekten.
Mit solchen Modellierungen kann man sich später noch genug rumschlagen. Zumal diese Beschreibung natürlich stark vereinfacht ist und jede Implementierung außen vor lässt.
Deswegen zu deinem Hauptproblem.
Du überträgst halt keine Daten zwischen den Objekten. "Eingabe_IP(int)" ist keine Klasse, sondern eine globale Funktion.
Du könntest eine IP-Klasse haben, eine Eingabe-Funktion und eine Ausgabefunktion in einen Input/Output-Klasse. Dann würdest du in main sowas machen wie:
Bei so einem simplen Beispiel finde ich es schwer Eingabe und Ausgabe zu trennen, weil es diskussionswürdig ist für eine einzelne Funktion (Ausgabe) eine neue Klasse zu erzeugen.
P.S.: "#pragma once" ist kein Teil des offiziellen Standards. Das ist für Anfänger einfacher und wird breit unterstützt, aber da du vorher auch nach dem Entfernen von Features mit dem neuen Standard C++11 gefragt hattest: #pragma once ist kein Standard.
Außerdem solltest du dir schnell einen ordentlichen Stil zulegen. D.h. bei der Verschachtelung von Schleifen immer weiter einrücken, nach jedem Befehl/Semikolon eine neue Zeile usw. Das vereinfacht das Lesen des Codes sehr.
Ach gut, danke.
Mir ist die Ausgabe eine eigene Klasse, oder auch nur einen eigenen Programmteil zu geben, auch nicht so genehm (wie gesagt kompakter Code sind mir die liebsten), aber mein Dozent hat mir was die Struktur angeht, entsprechend Weisung erteilt. JA, Sir
Ehrlich gesagt, müsste ich jetzt Eingabe, Ausgabe und Verarbeitung in Klassen stopfen. Anderseits ist es in diesem Fall ja eigentlich nicht nötig und ich eigentlich zu faul
P.S.: "#pragma once" ist kein Teil des offiziellen Standards.
Das weiß ich (jetzt), aber VS nicht. Die Grundstruktur habe ich mit dem Wizard erzeugt, weil VS (was mein Dozent selbst mit entsetzen feststellen musste) Probleme hat manuell angelegte Header zu sehen. Das ist kein Scherz!
Oder auch.
Ich inkludiere einen VS erzeugten Header in main per Hand und er naddelt rum. Also das Programm meint das bsp. Eingabe.h nicht existieren würde. Nutze ich diese Vervollständigungsfunktion, funktioniert es. Also Eingabe.h ist plötzlich da...
Ich will eigentlich VS nicht nutzen, aber mein Dozent meinte ich sollte es. Wohl deswegen, weil es später im Betrieb wohl auch mehr genutzt wird, als andere Entwicklungsumgebungen.
Außerdem solltest du dir schnell einen ordentlichen Stil zulegen. D.h. bei der Verschachtelung von Schleifen immer weiter einrücken, nach jedem Befehl/Semikolon eine neue Zeile usw. Das vereinfacht das Lesen des Codes sehr.
In Tschernobyl dürften zum einen keine Computer zum Einsatz gekommen sein. Ich tippe eher auf Regelung durch richtige elektrische Schaltungen.
Außerdem wurden bei Tschernobyl damals von den Leuten im Fahrstand, um einen Test durchzuführen, der eigentlich vor Inbetriebnahme hätte stattfinden und bestanden werden müssen (Beim ersten Mal bevor das Kraftwerk an Netz ging hat es nicht geklappt), einige Sicherungen absichtlich abgeschaltet. Die hätten mehrmals noch auf den roten Knopf mit "Notabschaltung" drücken können, wurden dann aber auch durch Politiker (hallo Sozialismus/Kommunismus: "Das Kraftwerk muss Planerfüllung betreiben!") dazu gedrängt es bis zum Ende durchzuziehen. Das Ende war halt "Kabumm".
Die Frage ist - kurz und prägnant - wie erzeuge ich die Daten-Klasse übergreifend?
Wenn ich das in Main mache, aber nicht in Eingabe, bekommt Eingabe nichts ab von dem Segen. Und bleibt die von mir gewünscht Kapslung der Daten erhalten?
Man ein weitere Frage:
Ich habe des öfteren gelesen, das im Rahmen der Weiterentwicklung von C++ einige Befehle entfernt werden. Meines Erachtens ist das Unsinn, da man bestimmt daran interessiert ist, das ein Compiler aus dem Jahre 2010, auch Code kompilieren kann der 1995 geschrieben wurde. Ist das nur eines von diesen "Fakten", die bei genauer Betrachtung keine Substanz haben?
also mit
Daten* ip1, ip2, ip3, ip4;
deklarierst/definierst du die variablen.
wenn du dann sowas machst wie:
ip1 = new Daten();
ip2 = new Daten();
ip3 = new Daten();
ip4 = new Daten();
(oder machst ggf. ne liste von daten)
dann initialisierst du die variablen.
und diese pointer kannst in den weiteren methodenaufrufen/klasseninitialisierungen (eingabe/verarbeitung) mit reinwerfen, damit diese zugriff auf diese datenobjekte haben.
somit existieren diese instanzen der klasse "Daten" im scope der mainmethode.
eine weitere, eher unschöne weise wäre es, dafür eine globale statische klasse zu erstellen, die deinen Datenvector speichert.
code aus 1995 unter MSVC10 zum laufen zu bringen ist an vielen enden echt schwer.
je nach verwendeten frameworks/apis kanns sein, dass man viel neu programmieren muss, oder es einfach nicht typenkompatibel ist.
damals waren diese ganze stream-klassen besonders unter windows noch ziemlich böse.
bin auch gerade dabei ein c++ projekt von 1992 auf heutige technik zu portieren und stoße immer wieder auf böse speicherallokationsfehler.
das ist besonders unschön, wenn von der zuverlässigkeit der anwendung leben abhängen.
da muss man erst jeden minifehler finden, bevor man das in produktion geben kann.
also mit
Daten* ip1, ip2, ip3, ip4;
deklarierst/definierst du die variablen.
wenn du dann sowas machst wie:
ip1 = new Daten();
ip2 = new Daten();
ip3 = new Daten();
ip4 = new Daten();
(oder machst ggf. ne liste von daten)
dann initialisierst du die variablen.
und diese pointer kannst in den weiteren methodenaufrufen/klasseninitialisierungen (eingabe/verarbeitung) mit reinwerfen, damit diese zugriff auf diese datenobjekte haben.
somit existieren diese instanzen der klasse "Daten" im scope der mainmethode.
eine weitere, eher unschöne weise wäre es, dafür eine globale statische klasse zu erstellen, die deinen Datenvector speichert.
U
nnötig kompliziert. Um Daten-Instanzen übergeben zu können, muß er nicht extra mit Pointern und new-Allozierungen rumeiern. Ganz normale auf dem Stack liegende Daten-Instanzen und Übergabe der Instanzen per Referenz tun's auch.
Code:
void functionThatUsesExistingInstances( Daten& first, Daten& second, Daten& third, Daten& fourth )
{
// do stuff with passed "Daten" instances
// ...
}
int main()
{
Daten ip1, ip2, ip3, ip4;
// ...
// pass "Daten" instances by reference ... function can modify state of passed instances
functionThatUsesExistingInstances( ip1, ip2, ip3, ip4 );
// ...
}
Das mit den Pointer halte ich im Moment auch zu kompliziert für dich und stimme da antred zu . Wenn du es so machst, sollte das locker für dich ausreichen. Ansonsten musst du dich wieder um das löschen kümmern und nunja, dazu solltest du erstmal andere Grundlagen verstanden haben. Um nochmal zu verdeutlichen was antred meinte.
Code:
void foo (int zahlInFunktion)
{
zahlInFunktion++;
}
void foo2 (int& zahlInFunktion2)
{
zahlInFunktion2++;
}
int main ()
{
int zahl = 1;
foo(zahl);
//nach dieser Funktion hat zahl immernoch den Wert 1
foo2(zahl);
//nach dieser Funktion hat zahl den Wert 2
int& andererName = zahl;
// zahl hat den Wert 2, andererName hat den Wert 2;
andererName++;
// zahl hat den Wert 3, andererName hat den Wert 3;
}
zahl wird in main deklariert und initialisiert. Für den ersten Funktionsaufruf der Funktion foo wird die Variable KOPIERT, in der anderen Funktion foo2 übergibst du sie per Referenz, d.h. das du nun auch innerhalb der Funktion die außen deklarierte Variable bearbeitest.
Um es noch stärker zu verdeutlichen: andererName ist auch eine Referenz und im Prinzip wirklich nur ein anderer Name für die Variable zahl. Wenn du ihren Wert änderst, dann eben auch den von zahl selber.
Das geht natürlich auch mit Objekten, nicht nur mit int Variablen. Ich bin mir auch nicht sicher ob du verstanden hast, wie lange eine Variable sichtbar ist und lebt . zahl lebt z.b. die komplette main Funktion durch und wird danach gelöscht. zahlInFunktion z.b. genauso. Sie wird beim Funktionsauruf von foo deklariert und bekommt einen Wert zugewiesen, lebt dann solange man in der Funktion ist und wird danach, beim Verlassen der Funktion gelöscht. Außerhalb der Funktion ist sie nicht sichtbar. Auf zahl kann man auch nur in der Main Funktion zugreifen. In der Funktion foo2 kannst du sie halt indirekt bearbeiten, weil du den Trick mit der Referenz machst.
Ich denke, wenn du das verstanden hast, solltest du auch dein Problem mit den Variablen Zugriffen lösen können, dann bleibt aber unter anderem noch das Problem der OOP . Ich hoffe mal das hilft dir ein wenig.
Verstanden habe ich es schon, hatte aber Probleme mit der C++ eigenen Logik. Ich lasse mich beispielsweise oft dazu verführen an eine Sache ran zugehen als sei C++ Quickbasic. Und das dies wohl kaum gutgeht siehst du ja
Was meinen Programmierstil angeht. Der mag vielleicht merkwürdig aussehen, aber solange ich noch lerne, möchte ich von diesen durch gestylten Stil (denn man mir ständig versucht aufzudrängen) absehen. Da ich eben mich darauf konzentrieren will zu verstehen und wenn der Syntax und die Struktur an sich für mich weniger genehm ist, lenkt es ab. Sicher, später ist es wichtig das auch andere aus meinem Code schlau werden, aber zur Zeit gelten andere Prioritäten.
Jedenfalls danke für eure Hilfe. Es funktioniert jetzt so wie ich will und ich denke ich bin bis nächsten Donnerstag fertig.
@ 1668mib
Das habe ich auch nicht gesagt. Es ging mir mehr darum zu erklären, das ich leider aus fünf Richtungen Stilvorschriften erhalte, die sich auch noch gegenseitig widersprechen. Viel zu viele denken sich selbst ein Denkmal errichten zu müssen in dem Sie andere dazu drängen etwas so aussehen zu lassen, wie sie es gern hätten.
Ich denke das ich das Recht habe einen eigenen Stil zu haben/ zu entwickeln. Zumal hoffe ich eigentlich weniger durch pures anschauen meines eigenen Codes ein besserer Programmierer zu werden. Es würde reichen aus ihm selbst schlau zu werden
Mir ist aufgefallen das du Code auskommentieren kannst, das alles grün ist. Aber das hilft nichts, wenn du die Prozessstrukturen nicht geistig mitverfolgen kannst. Jeder hat seinen eigenen Stil, einen eigenen Weg an eine Sache ran zu gehen. Dies spiegelt sich in deinem eigenen Code wieder.
Wenn ich konsequent denn Stil anderer nachmachen würde (und es dabei auch noch allem Recht machen würde, oder versuche dies zu tun), würde ich mich am Ende fragen ob ich das wirklich geschrieben habe und nicht mehr aus meinen eigenen Code schlau werden.