Vererbung und gleiches Interface/Verhalten
-
Hallo,
ich hatte aus Uebungszwecken mal ein bisschen ueber einen andern Thread hier, genauer gesagt den Thread von Spartaner bez. Schiffen die Waffen haben mit einer Prioliste, nachgedacht, spezieller ueber die einzelnen Waffen.
Zuerst wollte ich es so machen, dass ich eben eine Basis_Waffe Klasse schreibe (abstrakt) und dann die einzelnen Waffen davon erben lasse mit angepassten Parametern.
Nun, ich habe mir gedacht, dass alle Waffen ja eigentlich nur ein Array oder einen std::vector mit ihrer Prioliste, ein int das den Schaden angibt sowie die Methode fire() zum schiessen haben. Nun, dann bin ich auf die Idee gekommen dass man es vermutlich auch so machen koennte, dass man in Basis_Waffe das Array und das int (oder heisst es den int?) protected machen koennte und dann beim Konstruktoraufruf einer Waffe diese Parameter in der Basisklasse entsprechend anpasse und eben auch die Methode fire der Basisklasse einfach aufrufe (und ergo nicht mal virtuelle Funktionen braeuchte).
Frage 1: ist das so moeglich oder hab ich was uebersehen (sry, kann es gerade nicht ausprobieren... sonst haette ich das zuerst gemacht)
Frage 2: if(tolower(question1.answer)=="ja") welche Vor/Nachteile ergeben sich gegenueber der 1. Loesung.
Frage 3: in diesem Fall koennte man dann ja sogar nur eine Klasse Waffe erstellen, die dann im Konstruktor den Namen einer Waffe uebergeben bekommt und entsprechend die Parameter einfach setzt. So wie ich mir das denke wuerde das allerdings unuebersichtlicher und es waere schwerer dass gar nicht vorhandene Waffen erstellt werden (was ja schon durch nen kleinen Schreibfehler leicht passieren kann) Gaebe es auch Vorteile?Frage 4: Was wird im allgemeinen gemacht, wenn sich so eine Situation, wo sich nur die Parameter unterscheiden, ergibt?
-
Solange alle Waffen nach dem gleichen Grundprinzip arbeiten (du hast einen Namen und einen Basisschaden - und beim Schießen wird dieser Schaden (evt. modifiziert durch die gegnerischen Schilde) von den Hitpoints des Zieles abgezogen), reicht eine Klasse völlig aus. Problematisch wird dieses Design erst, wenn du Spezialwaffen integrieren willst, die von diesem Grundprinzip abweichen können (z.B. ein Traktorstrahl oder einen Paralyse-Strahler).
-
Ok vielen Dank. Im globalen also: wenn man mehrere "Typen" von irgendetwas hat, diese aber bis auf die Werte der Parameter gleich sind, dann erstellt man eine Klasse und setzt im Konstruktor die entsprechenden Werte (per if oder switch).
Nur eine Kleinigkeit dann noch: nehmen wir mal an in dem Waffenbeispiel gebe ich irgendwo dann an die Waffe-Klasse einen Namen der so nicht exisitiert (entweder verschrieben, oder vergessen in der Klasse hinzuzufügen, was auch immer), was macht man dann? Eine Exception werfen (es handelt sich ja offensichtlich um einen Fehler) oder eher vielleicht noch ein assert (ist ja ein Programmierfehler, nichts was durch eine Benutzereingabe passiert)? Das würde man dann aber eben auch erst zur Laufzeit merken und nicht, wie im Falle von mehreren Klassen schon beim kompilieren, richtig?
-
In dem Fall würde ich die Waffe nicht anhand ihres Namen spezifizieren, sondern anhand ihrer Parameter. (das bedeutet, du gibst im Ctor an, wieviel Schaden etc die Waffe verursachen kann)
(und im Endeffekt wird der Name nur noch verwendet, um anzuzeigen, wer womit auf wen geschossen hat)
-
Ok, so gehts auch.
Ich hatte mir jetzt noch überlegt die Waffennamen in einem enum zusammenzufassen und dann diese als int-Argument an den Konstruktor übergeben. Erstens kann dann der Konstruktor mit nem switch arbeiten und zweitens meckert der Compiler wenn ich mich irgendwie verschreibe oder eine nicht vorhandene Waffe übergebe. Wäre diese Methode auch akzeptabel?
Natürlich ist deine Methode besser (wie immer, hehe), mich würds nur mal interessieren.
-
Ja, geht auch - allerdings hast du es womöglich schwerer, neue Waffentypen anzulegen (und derartige Fallunterscheidungen machen den Code nur schwerer zu warten) und dir zur Laufzeit neue Raumschiffe zusammenzubauen (der User gibt den Waffennamen als String an, also müsstest du ihn zu einem enum umrechnen).
(PS: Arbeitest du zufällig mit 'Spartaner' zusammen?)
-
Nein nein, ehrlich gesagt arbeite ich nicht mal daran, auch wenn ich mir denke dass ich jetzt (wo ich Ferien hab, endlich, hehe) wohl versuchen werde das gleiche Programm zu Übungszwecken zusammenzustellen. Mir ist nur der Gedanke gekommen als ich über Spartaners Programm nachgedacht habe (siehe 1. Post) und ich mir dachte dass sowas auch noch öfter auftreten könnte vielleicht. Sollte ich das Programm schreiben werde ich auch versuchen irgendwie mit Spartaner in Kontakt zu treten, dann könnte man zusammen über die auftretende Schwierigkeiten reden (immer noch die beste Lernmethode meiner Meinung nach)
Eigentlich hatte ich nicht daran gedacht, dass der Benutzer sich selbst neue Raumschiffe zusammenbasteln können sollte, aber jetzt wo dus sagst... ist wohl echt Blödsinn etwas strikter zu machen als es sein muss, je flexibler desto besser eigentlich.
Danke dir, CStoll-sensei.