Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Do Jul 03, 2025 11:36

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 8 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Fr Jul 23, 2010 16:19 
Offline
DGL Member
Benutzeravatar

Registriert: Di Dez 03, 2002 22:12
Beiträge: 2105
Wohnort: Vancouver, Canada
Programmiersprache: C++, Python
Verschoben nach Allgemein: Hilfreicher Inhalt, der auch durchaus durch Suchmaschinen findbar sein sollte
Hi,

ich habe in meinem Framework eine Klasse "CISystem" welche die ganzen System geschichten kapselt und logischerweise auf jedem System verschieden ist.

Bisher habe ich es so gemacht, das JEDE Funktion von CISystem static ist, so kann ich z.B. im Code dann einfach:

CISystem::getNumMonitors();

aufrufen.

Jetzt unterstütze ich aber mittlerweile 5 Verschiedene Systeme (und es werden sicher noch mehr) - und das erhöht den Aufwand ziemlich wenn ich was an der System klasse ändere.. denn wenn ich z.B. ein "CISystem::doSomething()" unter dem Mac-System einführe, muß ich es gleichzeitig auch in den anderen Systemen einpflegen, obwohl es diese funktion dort evtl garnicht gibt - sie also immer 0 oder einen default wert zurück liefert.

Also hab ich vor das ganze weg von statischen methoden, hin zu einer normalen Klasse mit überladenen funktionen zu wandeln.

Es gibt dann eben ein CISystemBase von dem alle anderen sich ableitien und nur das überschreiben was sie brauchen/wollen.

Soweit kein Problem.

Was mich an der sache exterm stört ist, das die schöne, übersichtliche schreibweise wegwäre und das neue in etwa so aussähe:

CISystem::getSystem().getNumMonitors();

Gut, das ist jetzt auch nicht das schlimmste, aber irgendwie doppelt gemoppelt.. daher die frage, wie bekomm ich das eleganter hin??

eine globale Function getSystem() fände ich auch nicht so elegant.

Hat jemand eine Idee wie man das hübscher hinbekommt?

Aya~


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Jul 23, 2010 17:07 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7810
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Gehts dir rein um die Optik, den Schreibaufwand oder eventuelle Performance-Themen?

Bei Java gibts auch sowas: System.out.println(). Das zu tippen nervt. Deshalb verwende ich die IDE Template unterstützung. So braucht man nur sysout + Autovervollständigung tippen und fertig.

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Jul 23, 2010 18:17 
Offline
DGL Member
Benutzeravatar

Registriert: Di Sep 20, 2005 13:18
Beiträge: 1054
Wohnort: Dresden
Programmiersprache: C, C++, Pascal, OPL
Wie machst du es denn bisher z.B. bei getNumMonitors?
Fragst du in der Funktion das System ab oder arbeitetest du mit Compilerdirektiven?

Mit diesen dürfte das ganze doch recht schön und einfach umsetzbar sein.

Oder du hast eine CINullSystemklasse, die bei jeder Methode immer 0 zurückliefert aber alle Funktionen erstmal definiert.
Dann hast du z.B. eine CIWindowsSytem.h (oder ähnlich), eine CIMacSystem.h usw., wobei jede dieser Headerfiles stets die gleiche Kindklasse CISystem definiert, weshalb zwei Headerdateien auch nichts gleichzeitig nutzbar wären, und du bindest per Compilerdirektive (dabei nur an einer Stelle und nicht überall) immer die richtige ein (oder erstellst eine identische Kindklasse, falls du das System noch gar nicht untersützt).

LG Ziz

_________________
Denn wer nur schweigt, weil er Konflikte scheut, der macht Sachen, die er hinterher bereut.
Und das ist verkehrt, denn es ist nicht so schwer, jeden Tag zu tun als ob's der letzte wär’.
Und du schaust mich an und fragst ob ich das kann.
Und ich denk, ich werd' mich ändern irgendwann.

_________________Farin Urlaub - Bewegungslos


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Jul 23, 2010 20:19 
Offline
Forenkatze
Benutzeravatar

Registriert: Mi Okt 22, 2003 18:30
Beiträge: 1945
Wohnort: Närnberch
Programmiersprache: Scala, Java, C*
Ahoi,

ich hab drei Vorschläge, zwei davon sind aber nur detailliertere Ausführungen des bisher gesagten.

#1
Kennt C++ static imports? Bei Java kann man statische Methoden so in andere Dateien importieren, dass man nichtmehr die Klasse davorschreiben muss.
Das würde also aus sowas:
Code:
class CISystem {
    public static int getNumMonitors() { ... }
}

[...]

import stuff.CISystem;

int numberOfMonitors = CISystem.getNumMonitors();


Sowas machen:

Code:
import static stuff.CISystem.getNumMonitors;

int numberOfMonitors = getNumMonitors();


Wenn C++ sowas kann, könntest du doch einfach das "getInstance()" (was ja statisch ist), in z.B. "environment()" umbenennen und könntest im Code dann:
Code:
environment().getNumMonitors();

schreiben ;)

#2
prinzipiell schreit das, was du möchtest, tatsächlich nach einem Interface (oder in deinem Fall einer abstrakten Oberklasse) und verschiedenen, konkreten Implementierungen. Und dann bräuchtest du natürlich irgendwo eine Instanzvariable. Die musst du ja nicht zwingend mit "getInstance()" erreichbar machen, kannst ja auch was schöneres nehmen ;)

z.B. Application::environment->getNumMonitors()

wobei environment einfach ein public static field von Application ist, in welches ganz zu Beginn die konkrete Implementierung reingesteckt wird...
environment = new MacEnvironment();

so in der Art ;)
Ist vielleicht etwas hübscher als CISystem::getInstance()->getNumMonitors();

#3
Oder du machst es so wie Ziz und wie es die Java Runtime macht. Dort hast du kein explizites "Interface" oder ne abstrakte Klasse... Sondern im Endeffekt durch den Preprocessor verschiedene Implementierungen und für den Code sieht es so aus, als gäbe es nur eine.
Bei Java wären das die verschiedenen Java Runtimes für die Plattformen.
Dagegen spricht vor allem deshalb nichts, weil du das ja nicht zur Laufzeit austauschen können musst.

Tellerrand:
Das ist übrigens einer der Bereiche, wo Scala glänzt. Dort gibt es neben Klassen auch Objekte, die man so hindeklarieren kann. Die funktionieren dann im Endeffekt wie Singletons, werden aber ohne ein getInstance() angesprochen ;)

Grüße,
~ Frase

P.S.: Was macht das überhaupt im Offtopic? Wär das nicht eher was für Allgemein?

_________________
"Für kein Tier wird so viel gearbeitet wie für die Katz'."


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Jul 23, 2010 21:04 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Zitat:
#1 Kennt C++ static imports?

Ja, das ist ein schönes Feature von Java. In C++ gibt es sowas aber leider nicht.

Bei Variante #2 sehe ich die Gefahr das man versehentlich auf Application::environment schreibend zugreift.

#4
Meine Standardlösung sieht in der Regel etwa so aus:

Code:
class Klasse {
   public:
      static inline Klasse* instance() {
         if (!m_instance) {
            m_instance = new Klasse();
         }
         return m_instance;
      }

      static inline void destroy() {
         delete m_instance;
      }


      // nicht statisch
      void eigentlicheFunktionalitaet();

   private:
      Klasse();
      ~Klasse();

      static Klasse* m_instance;
};

Klasse* Klasse::m_instance = NULL;

Klasse::Klasse() {
   // ...
}

Klasse::~Klasse() {
   // ...
   m_instance = NULL;
}


Benutzt wird das dann so:
Code:
Klasse* klasse = Klasse::instance();
klasse->eigentlicheFunktionalitaet();

Das hat den Vorteil das du das lokal dann so nennen kannst wie du es gerade haben willst. Z.B. ist es ja dann kein Problem wenn die Variable einfach nur "k" heißt.

Wird das Singleton an einer Stelle häufig genutzt legt ich meistens auch ein Klasseanttribut an und initialisiere das nur einmal im Konstruktor der jeweiligen Klasse.

#5
Wenn du ein Fan von Markos bist könntest du auch ein Marko definieren. Etwa so:
Code:
#define KLASSE (*Klasse::instance())


Dann kannst du schreiben:
Code:
KLASSE.eigentlicheFunktionalitaet();

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Sa Jul 24, 2010 00:21 
Offline
Forenkatze
Benutzeravatar

Registriert: Mi Okt 22, 2003 18:30
Beiträge: 1945
Wohnort: Närnberch
Programmiersprache: Scala, Java, C*
Coolcat hat geschrieben:
Bei Variante #2 sehe ich die Gefahr das man versehentlich auf Application::environment schreibend zugreift.

Joa na gut, dann kapselt man die Variable halt noch weg:

Application::environment()->getNumMonitors()

ist ja auch kein Weltuntergang ;)

_________________
"Für kein Tier wird so viel gearbeitet wie für die Katz'."


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Sa Jul 24, 2010 00:24 
Offline
DGL Member
Benutzeravatar

Registriert: Di Dez 03, 2002 22:12
Beiträge: 2105
Wohnort: Vancouver, Canada
Programmiersprache: C++, Python
Coolcat hat geschrieben:
#5
Wenn du ein Fan von Markos bist könntest du auch ein Marko definieren. Etwa so:
Code:
#define KLASSE (*Klasse::instance())


Dann kannst du schreiben:
Code:
KLASSE.eigentlicheFunktionalitaet();


Da es mir nur um die optik des ganzen geht, die idee mit dem Macro ist super! :)
Ich finde es einfach nervig und unschön wenn im Code etwas á la:

Code:
CISystem::getSystem().getNumMonitors()


steht.. ich finde einfach das ist irgendwie doppelt gemoppelt ^^

Und so sieht es einfach hübscher aus:

Code:
#define CICurrentSystem() CISystem::getSystem()

CICurrentSystem().getNumMonitors();



Danke~
Aya


Zuletzt geändert von Aya am Sa Jul 24, 2010 00:32, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Sa Jul 24, 2010 15:09 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2623
Wohnort: Berlin
Programmiersprache: Go, C/C++
Von Interfaces rate ich dir ab, da hab ich schmerzhafte Erfahrungen gemacht, da ja ein Interface virtuelle methoden nutzt, werden runtime checks eingeführt und es gibt extra functions calls, pro ableitung und noch den mehraufwand der rtti. Das drückt die Performance spürbar, wenn man solch eine Methode in einer Echtzeitanwendung immer wieder aufruft.
http://www.gamedev.net/reference/programming/features/AbsPolyOpt/ Hier gibs auch ein guten Artikel zu dem Problem.

Das verpacken in ein Makro ist auch meine Empfehlung, das mach ich genauso.
Z.B. #define Console RadonFramework::IO::Console::GetInstance()
oder #define LogInfo(X) RadonFramework::IO::Log::GetInstance().Add(X,RadonFramework::IO::Log::InfoChannel,__LINE__,__FILE__)
Damit erzielst du auch den gleichen Effekt wie das von Frase angesprochende Scala Feature, dass man Klasse.Methode() machen kann und nicht erst eine Instanz erstellen muss. Dieses Features gibt es übrigens auch in C#.

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 8 Beiträge ] 
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 13 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.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.008s | 14 Queries | GZIP : On ]