ich hatte vor einem Jahr etwa relativ viel mit Java programmiert und da war es üblich für mehr oder weniger alle variablen Getter und Setter Methoden zu machen, was ja eigentlich auch ein schönerer Styl ist als einfach direkt die variable als public zu deklarieren.
Jetzt mittlerweile bin ich ja auch C++ umgestiegen und treibe das spiel mit den Getter und Setter methoden noch ein stück weiter.. Ich mache für absolut JEDE variable Getter und Setter und spreche die variable auch ausschließlich über diese an.. auch intern in der Klasse. Dadurch wird die variable selbst wirklich nur im Getter und Setter direkt angesprochen.
Was ich mich da jetzt frage ist... ich mag das ganze und finde es übersichtlicher (auch wenn oft die Getter und Setter einfach nur die variable setzen, bzw. returnen, ohne etwas damit zu machen).. aber ist es sinnvoll?
Ich meine Sinnvoll in sachen geschwindigkeit hauptsächlich... macht sich das irgendwie negativ bemerkbar wenn ich die variable nochmal über ne funktion zurückliefe statt direkt? (Bei einer natürlich nicht, aber bei 10000?)
Ich rede natürlich nur von den standard arten: int, float, char und pointer.. structs etc übergeb ich dann in der Regel als Pointer.
Ach ja, und apropos Pointer.. ich kann ja eine Variable als Referenz übergeben (mit & in der funktions deklaration) oder als Pointer.. macht das irgendeinen unterschied ausser wie ich die Variable dann innerhalb der Funktion benutze?
Wenn Du die Optimierungen nicht gänzlich abgeschaltet hast, sollte er die Gets und Sets, weil meistens sehr kompakte Funktionen, Inlinen, heißt er ruft nicht die Funktion auf, sondern pakt den entsprechenden Code direkt an die Stelle des Aufrufs.. Kannst Du leicht prüfen, indem du in der Release Version übersetzt, Break Point setzt und dir den zugehörigen Assembler Code anzeigen lässt, wenn nicht, mancher C++ Dialekt nimmt das Schlüsselwort "inline" ernst; Den Performanceverlust hast du höchstens beim Übersetzen des Programms, aber nicht beim Ablauf. Ansonsten sind Gets und Sets gut, weil Du dann im Nachhinein den Code und Funktionalität bezüglich dieser Variable leicht ändern kannst, ohne daß das von außen einer merkt. Ob man die privaten Variablen dann in der Klasse direkt verwendet oder nicht, ist denke ich Geschmackssache; den Funktionalitätswechsel kann man da imho nicht anführen, weil wenn das passiert muss man so oder so sehr genau prüfen ob die ganzen Funktionen noch das machen, wie sie spezifiziert sind.
Aya hat geschrieben:
Ach ja, und apropos Pointer.. ich kann ja eine Variable als Referenz übergeben (mit & in der funktions deklaration) oder als Pointer.. macht das irgendeinen unterschied ausser wie ich die Variable dann innerhalb der Funktion benutze?
Ich denke es passiert genau das selbe (ASM Code anschaun ), nur daß du unterschiedlichen Aufwandt betreibst, um mit dem Ding am Ende zu arbeiten.
Registriert: Do Sep 25, 2003 15:56 Beiträge: 7810 Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Für alles sollte man nicht get/set anbieten. Hin und wieder macht es sinn, variablen bewusst zu verstecken. Das Prinzip sollte heißen, nur soviel zugänglich zu machen wie wirklich nötig ist. Z.B. machen setter für IDs eigentlich keinen Sinn. Wenn man die Klasse erstellt kann man im Kostruktor z.B. die ID mitgeben und später sollte sie nie mehr geändert werden.
Für Sachen wie Serialisierung kann das aber probleme machen. (Bin mir da gerade nicht sicher ob man dem durch protected/private Getter/Setter begegnen kann.)
_________________ Blog: kevin-fleischer.de und fbaingermany.com
Für alles sollte man nicht get/set anbieten. Hin und wieder macht es sinn, variablen bewusst zu verstecken. Das Prinzip sollte heißen, nur soviel zugänglich zu machen wie wirklich nötig ist. Z.B. machen setter für IDs eigentlich keinen Sinn. Wenn man die Klasse erstellt kann man im Kostruktor z.B. die ID mitgeben und später sollte sie nie mehr geändert werden.
Für Sachen wie Serialisierung kann das aber probleme machen. (Bin mir da gerade nicht sicher ob man dem durch protected/private Getter/Setter begegnen kann.)
Ja klar, für dinge die nicht nach aussen getragen werden gibt es natürlich auch keine getter und setter.. das ist ja logisch
Aber z.B. bei meinem TextureLoader die TexturID von OpenGL.. die ist ja so ein beispiel wie du meinst, dafür gibt es logischerweise nur einen Getter, keinen setter
Registriert: Di Mai 18, 2004 16:45 Beiträge: 2623 Wohnort: Berlin
Programmiersprache: Go, C/C++
Getter und Setter sind ein absolutes muss und gutes foo.
Du sollst Getter und Setter inline machen, was am einfachsten geht ist, wenn du Implementierung direkt nach der Deklerierung machst. Dann wird es bei gcc und VS einheitlich umgesetz, sonnst kannst über inline tag probieren hab ich in der Praxis aber selten gesehen.
Code:
class TBla
{
protected:
int m_iZahl;
public:
void SetZahl(int Zahl){m_iZahl=Zahl;};
int GetZahl(){return m_iZahl;};
}
_________________ "Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren" Benjamin Franklin
Getter und Setter sind ein absolutes muss und gutes foo. Du sollst Getter und Setter inline machen, was am einfachsten geht ist, wenn du Implementierung direkt nach der Deklerierung machst. Dann wird es bei gcc und VS einheitlich umgesetz, sonnst kannst über inline tag probieren hab ich in der Praxis aber selten gesehen.
Code:
class TBla
{
protected:
int m_iZahl;
public:
void SetZahl(int Zahl){m_iZahl=Zahl;};
int GetZahl(){return m_iZahl;};
}
Umh, ich finde Implementierungen im header sind absolut schlechter Programmierstyl.. Das macht den Code nur unnoetig Unuebersichtlich.. Dafuer gibt es ja extra "inline".
Registriert: Di Mai 18, 2004 16:45 Beiträge: 2623 Wohnort: Berlin
Programmiersprache: Go, C/C++
Wenn wer von guten oder schlechten Programmierstiel redet bekomme ich ab und zu schon ein gribbeln in den Fingern.
Programmierstiel hat nichts mit Codestyle zu tun..., da bin ich sehr genau . Diese Art von Inline Code ist Standardisiert und hat auch seinen guten Grund, was bedeutet, dass es kein schlechter Programmierstiel sein kann.
Zum Thema schlechter Codestiel, ja mag sein das es nicht so toll aussieht aber es ist übersichtlicher und egal ob industrie oder privater code ich hab vieleicht 1-2 mal in meinem ganzen Leben Code mit inline tag(bei einzeilern) gesehen. Die Alternative wäre einen 4 Zeiler im C++ Code zu schreiben und bei 30-40 getter und setter Methoden(120-160Zeilen Code+30-40 Leerzeilen) ist dein Code dann noch viel unübersichtlicher, da du einfach mal mehrere hundert Zeilen Code hast die du überscrollen musst. Deshalb habe auch ich mir angewöhnt einzeiler inline funktionen in den header zu verfrachten.
Mehrzeiligen Inlinecode habe ich bisher noch nicht verwendet, wo es sinn machen würde den inline tag in einer cpp file zu verwenden.
Inline verwendet man in der Regel nur für Getter und Setter, da es bei größeren Codefetzen einen negativen Effekt hat und das Progamm langsamer, größer macht und langsamer compilieren lässt.
Ich finde auch, dass man das inline Feature nur in sehr wenigen Fällen nutzen sollte, denn es lockert das Rechtesystem(public,private,protected,...) von Klassen auf und macht bei zu häufiger verwendung halt Compilierprozess und Ausführungszeit langsamer.
Ein grund für Inline bei Getter und Setter ist die Geschwindigkeit, da für ein Getter und Setter ohne inline man push und pop sowie call befehl hat und bei inline diese einfach entfallen(großer Performancegewinn).
Eine gute Seite zum Thema gibt es hier.
There are no simple answers Dieser Kommentar, aus dem Link, trifft den Nagel auf den Kopf, denn es hängt immer von der Nutzung und den Gegebenheiten ab, ob es überhaupt Sinn macht Inline zu verwenden.
Teilweise sind Setter ja nicht immer nur bla=blupp; sondern auch noch komplexere Strukturen, die aufgerufen und ausgeführt werden und da würde ich z.B. schon überlegen, ob es inline wird und die schreibt man logischer weise auch dann in den cpp file und nicht wie den einzeiler in die hpp.
Denn des so größer die Header file wird, des so länger dauert das compilieren, da ein Header oft mehrfach gebraucht wird.
Das merk ich z.B. schon bei meinem Projekt Karmarama.
Beim normalen compilieren kann man compilierzeit auch vernachlässigen aber beim debuggen, wo man zig mal in der minute compiliert, da macht es schon einiges aus, ob es 3sekunden schneller geht.
PS:Falls der Text ein bischen böse oder ähnliches rüber kommt, dass war nicht mein Ziel.
_________________ "Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren" Benjamin Franklin
Wie gesagt im normalfall braucht kein Mensch "inline" angeben, weil das der Compiler mit aktivierten Optimierung recht verlässlich selbst erledigt. Man siehe hier einmal die gcc dokumentation:
Option -O1, also einfachste optmierungsstufe enthält: -finline-small-functions
Auf der selben Seite unten steht was das induziert:
Zitat:
-finline-small-functions Integrate functions into their callers when their body is smaller than expected function call code (so overall size of program gets smaller). The compiler heuristically decides which functions are simple enough to be worth integrating in this way.
Enabled at level -O2.
Jetzt fragt aber bitte nicht, warum da "Enabled at level -O2" steht, da ist sich die Dokumentation wohl nicht ganz einig Jedenfalls werden sehr einfache Gets und Sets auf diese weise geinlined. Ganz AUTOMATISCH Wer größere Abfragen drin hat kommt zwar schnell an die Grenzen, das aber sollte ausgewogen spätestens ab mit O3 geschehen... Andere Compiler handeln das natürlich anders, aber da heissts halt nachschaun. Im Normalfall bracuht sich da aber niemand gedanken zu machen; und wenn ich das richtig gelsen habe ignoriert der gcc angegebene inlines, wenn keine Optimierungen eingeschaltet sind... Es ist einfacher Optimierungen anzuschalten, die diese Entscheidung im Schnitt besser treffen, als man selbst und wenns wirklich um alles geht hilft auch noch "Profile-Guided Optimization", ist aber auch im großen und ganzen AUTOMATISIERT...
Das Problem mit dem Überscrollen halte ich dagegen für seltsam, weil die meisten Entwicklungsumgebungen kein Problem damit haben, daß der Entwickler Regionen anlegt, die mit einem Klick oder Shortcut ausgeblendet werden können; dann brauche ich nichts mehr zu überscrollen. Zu den headerfiles zitiere ich einfach mal "Bjarne Stroustrup"
Zitat:
A header file may contain: [...] But never Ordinary function definitions char get() { return *p++; } Data definitions int a; Constant aggregate definitions tbl[] = { /* .. */ };
Der Sinn ist ja auch ganz klar: Headerfiles sollen dem Sinn nach Spezifikationen sein; Implementierung steht woanders. Aber TAK, ich muss zugeben, so ganz klar ist mir jetzt nicht, was du mit dem Überscrollen genau ausdrücken wolltest und wo du nun meinst das solcher Code hingehört
Registriert: Di Mai 18, 2004 16:45 Beiträge: 2623 Wohnort: Berlin
Programmiersprache: Go, C/C++
Einzeiler die inline seien sollen, pack ich in den header, weil es einfach übersichtlicher und überwiegend performanter ist und mehrzeiler inline pack ich in die cpp file.
_________________ "Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren" Benjamin Franklin
Einzeiler die inline seien sollen, pack ich in den header, weil es einfach übersichtlicher und überwiegend performanter ist und mehrzeiler inline pack ich in die cpp file.
Das mag geschmacksache sein ob es übersichtlicher ist, denn dadurch muß man immer erstmal rausfinden ob der getter im header oder in der cpp implementiert ist.. also es ist halt nicht alles an einem fleck, sondern überall verteilt... aber wie gesagt, das ist geschmackssache.
Wie aber machst du das wenn du eine Header datei mehr als 1x includest'? Dadurch solltest du eigentlich linker probleme bekommen sofern der compiler das nicht automatisch dann als inline umbastelt..
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Aya hat geschrieben:
Wie aber machst du das wenn du eine Header datei mehr als 1x includest'? Dadurch solltest du eigentlich linker probleme bekommen sofern der compiler das nicht automatisch dann als inline umbastelt..
Dazu gehört doch in C++ sowieso um jeden Header ein entsprechende Konstrukt. Denn sonst würdest du ja alleine schon mit den Typen, Konstanten etc. Probleme bekommen.
Wie aber machst du das wenn du eine Header datei mehr als 1x includest'? Dadurch solltest du eigentlich linker probleme bekommen sofern der compiler das nicht automatisch dann als inline umbastelt..
Dazu gehört doch in C++ sowieso um jeden Header ein entsprechende Konstrukt. Denn sonst würdest du ja alleine schon mit den Typen, Konstanten etc. Probleme bekommen.
Code:
#ifndef __blah_h
#define __blah_h
...
#endif
Oder missverstehe ich die Frage gerade?
Ja das konstrukt ist schon richtig, aber das hilft nur wenn eine header datei innerhalb von einer CPP datei mehrfach includiert wird (auch über umwege).
Denn jede CPP datei wird ja separat erstmal zu nem *.o compiliert. Das was da intern in dem Header per #define deklariert wird, gilt immer nur für die aktuelle *.o.
A.cpp wird compiliert. Der compiler öffnet die A.h und includiert das die Main.h in dieser. Hier wird jetzt das #define auf true gesetzt.. jetzt includiert er die Main.h, ignoriert aber den inhalt weil ja #define gesetzt ist.
Bei B.cpp wurden die defines jetzt wieder resettet, ist ein komplett eigener compilier-schritt.
Wäre das anders, würde B.cpp den header ja garnicht kennen.
Wenn man jetzt ne funktion im Header direkt implementiert funktioniert das compilieren der cpp dateien noch problemlos, aber beim linken gibt es dann halt das problem das die funktion doppelt existiert..
Es ist nicht so problematisch das diese funktionen mehrfach exestieren, der linker erkennt dieses. Es gibt sogar zwei fälle in denen der code sogar im header stehen muss: Templates und inline funktionen. Bei inline funktionen ist es sehr wahrscheinlich, das das inline ignoriert wird wenn es nicht zur compilezeit verfügbar ist (.z.B. weil es in einem anderem file steht)
Allerdings scheint es durchaus möglich zu sein sich bei den templates nicht daran zu halten, in diesem fall ist der compiler quasi gezwungen den template code im objekt file zwischen zu speichern und es dem linker zu überlassen, diesen nach bedarf zu compelieren....
Allein durch die existens von templates muss der linker aber in der lage sein mehrfachen code zu erkennen, da eine template klasse auch statische member enthalten könnten, die einmalig sind.
Mehrfacher code durch code in den headern hat einen großen Nachteil: der compiler kann im extrem fall um eine Größenordnung mehr zu tun haben, wenn diese Header oft benötigt werden. Des jedes mal wird dieser code mitcompeliert werden....
Der mehrfach include schutz hat damit im Prinip nichts zu tun....
Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.