C++ Designproblem (fast gar kein Code ^^)
-
Morgen!
Ich habe folgende Situation:
Mit einer selbstentwickelten SQL-Klasse kann ich mich bequem zu einer Datenbank verbinden, Abfragen machen oder Statements "abgeben".
Jetzt habe ich das Problem das meine Datenbank 4 Tabellen haben wird, die sich aber sehr ähneln. Die Methoden für diese Datenbanken sind momentan noch in der SQL Klasse enthalten was ich aber für falsch halte, dass Ding sieht ungefähr so aus:
// Ganz grob skizziert class MySQL { public: SQLRETURN InsertTabelle1(string q, bool,bool,bool,bool,bool,bool,bool,bool); SQLRETURN InsertTabelle2(string q, int); SQLRETURN InsertTabelle3(int q, int p, bool,bool,bool,bool,bool,bool,bool,bool); SQLRETURN InsertTabelle4(int q, int p, int s); SQLRETURN Import(string file); SQLRETURN Export(string table); SQLRETURN Delete(string table, unsigned int id); SQLRETURN CreateTableTabelle1(); SQLRETURN CreateTableTabelle2(); SQLRETURN CreateTableTabelle3(); SQLRETURN CreateTableTabelle4(); };
Wie man sieht ist vieles einfach doppelt, also dachte ich mir das ich erstmal eine logische Trennung zwischen der MySQL Klasse vornehme und eine eigene Klasse Table erstelle. Diese soll dann Import() Export() und Insert() anbieten, wobei Createtable einfach nur der ctor sein wird.
Ich vermute das wird jetzt das erste mal sein das ich eine abstrakte Basisklasse verwende;
**
Import und Export sollen virtual werden, da diese bei jedem Table dabei sein müssen. Insert aber auch, aber insert kann ich nicht virtual machen da jede Tabelle eine unterschiedliche Anzahl an Parametern hat.
Gibt es einen virtual-Befehl der nur besagt das eine Funktion da sein muss (Parameterzahl egal?)? Oder wie könnte man das sonst lösen?**Danke
-
Explizit nicht.
Virtuelle Funktionen bieten Polymorphie, sind aber nicht dazu gedacht, ein bestimtme interface zu forcieren.
Da die verschiedenen abgeleiteten Klassen verschiedene Parameter bekommen, mußt du zu Aufrufzeit die eigentliche Klasse kennen. (Aufruf über basisklassenreferenz ist nicht möglich)
Wenn du nur die existenz forcieren willst, bekommt man evtl. per templates was hin, aber das ergibt IMO keinen Sinn...
-
Macht es denn sinn eine virtuelle Basisklasse zu erstellen die die Methoden vorschreibt die jede Tabelle haben muss außer der insert?
Ansonsten wei´ß ich nicht wie ich das am besten realisiere
-
Eine Basisklasse mit virtuellem Methoden ist sinnvoll, wenn du über die Basisklasse Funktionalöität zur Verfügung stellst - z.B.
class CTabelle { public: virtual void Create() = 0; virtual void Import(string file) = 0; }; class CTabelle1: public CTabelle { public: virtual void Create() // override CTabelle:: { ... specific for Tabelle 1 ... } virtual void Import(string file) // override CTabelle:: { ... } void Insert(...); }; class CTabelle2: public CTabelle { ... ebenso .... }; // Hier nuzt dire die Polymorphie etwas: void CreateAndImport(CTabelle & tabelle, string file) { tabelle.Create(); tabelle.import(file); };
CreateAndImport ist generisch für alle Tabellenarten, kannst du mit Tabelle1 - Instanz, oder Tabelle2-Instanz aufrufen.
Wenn du das nicht brauchst, sind virtuelle Funktionen auch nicht notwendig.
Die Tabellenklassen zu trennen wäre trotzdem nicht schlecht.
-
@peterchen: Wieso kann man die CreateAndImport-Methode nicht in die Basisklasse klatschen?
Der Witz an virtuellen Methoden/Polymorphie ist ja gerade, dass ich nur die Basisklasse (CTabelle) kennen muss und die virtuellen Methoden werden von den abgeleiteten KLassen (CTabelleX) "ersetzt"?!Oder wie erklärst du dir, dass folgendes Beispiel funktioniert:
class A { public: void ProcessVritFunc(void); virtual void testfunc(void) = 0; }; void A::ProcessVritFunc(void) { testfunc(); } class B : public A { public: virtual void testfunc(void); }; void B::testfunc(void) { cout << "B" << endl; } class C : public A { public: virtual void testfunc(void); }; void C::testfunc(void) { cout << "C" << endl; } int main(int argc, char *argv[]) { B b; C c; b.ProcessVritFunc(); c.ProcessVritFunc(); return 0; }
[edit]Wieso muss also CreateAndImport eine eigne Funktion mit dem Parameter tabelle sein, statt eine Methode der Basisklasse?[/edit]
-junix
-
Hmmm... ich hätte alles _genau_ lesen müssen... Das löst nämlich nicht unbedingt das Problem von MinusFuenfzehngradBrrr...
-junix
-
@peterchen: Wieso kann man die CreateAndImport-Methode nicht in die Basisklasse klatschen?
Hab ich nicht gesagt.
Wenn du die gleiche Implementation verwendest (evtl. über Konstruktor-Initialisierte member parametrisiert), geht das natürlich.
Mein Beispiel zielte auf den Fall ab, das die implementationen zu unterschiedlich sind.Wieso muss also CreateAndImport eine eigne Funktion mit dem Parameter tabelle sein, statt eine Methode der Basisklasse?[
fat vs. lean class interface. Ist bis zu einem gewissen Punkt Geschmackssache, ich bit (falls es ernst wird) Anhänger der non-friend-non-meber - Clique.
CreateAndImport war als simples Beispiel für die Nutzung von Polymorphie gedacht.
Was ich eigentlich sagen wollte: Wenn -15Brr polymorphie nicht benötigt, muß er die Methoden auch nicht virtuell machen.
-
hab deine zweite reply erst nach meinem post gesehen
-
@MinusFuenfzehngradBrrr
Was ich ned versteh, iss warum du den Zugriff auf SQL-Ebene generalisieren willst .... was macht das fuer dich fuer einen Sinn.
In der "Normalen" programmierwelt hat man generischen Zugriff auf die SQL Funktionalitaet, mittels den Bibos die man verwenden kann (mysql++, mysql.h(C-Interface) ) .... DIe muessen aber so generisch sein, damit man auch alle SQL Funktionen hat.
Spezialisieren tut man seine, die erste Schicht drueber, dann eigentlich schon auf die eigenen Abstrakten Anforderungen.
Also sprich, dass sich zum Besipiel eigene Personen/Abteilungen .. etc -Objekte selbst aus der datenbank serialisieren koennen.
Was macht eine halb spezialisierte schicht dazwischen nochmal fuer einen Sinn.
Aus tabellen extracte(exporte) erstellen die man wieder einlesen(importieren) kann, sollte die DB in ihrem Toolset selber mitbringen ???Was fuer ein programm / lib / framework genau willst du schreiben und wer soll das einsetzen ?
Ciao ...