Forum: PC-Programmierung C++ Header Struktur


von Axel471 (Gast)


Lesenswert?

Hallo MC,

ich zerbreche mir gerade den Kopf, wie man in C++ Header sinnvoll 
inkludiert. Das Problem ist folgendes:

auto.h:
1
#include "reifen.h"
2
3
class auto
4
{
5
   public:
6
         auto();
7
         ~auto();
8
9
         int geschw();
10
         int ort_x();
11
         int ort_y();
12
         int ort_x();
13
14
   private:
15
         int geschw;
16
         int x,y,z;
17
18
         reifen r1;
19
         reifen r2;
20
         reifen r3;
21
         reifen r4;
22
}

Wenn ich nun irgendwo im Hauptprogramm "Auto.h" inkludiere, dann sollen 
nur die public-Funktionen verwendbar sein. Aber ich inkludiere ja 
"reifen.h" gleich mit, d.h. dass im Hauptprogramm auch Reifen 
instantiiert werden können, die sollen aber verborgen sein.

"reifen.h" in "auto.h" zu inkludieren, macht m.M.n. Sinn, aber wie 
struktiere ich es so, dass die Reifen verborgen bleiben?

Gruß,
Alex

von icke (Gast)


Lesenswert?

Inkludiere reifen.h nur in auto.cpp.
In auto.h bruchst du nur eine Deklaration  mit "class reifen" machen.

Den Rest erledigt der Linker.

von Axel471 (Gast)


Lesenswert?

So etwa?
1
class reifen;
2
3
class auto
4
{
5
   public:
6
         auto();
7
         ~auto();
8
9
         int geschw();
10
         int ort_x();
11
         int ort_y();
12
         int ort_x();
13
14
   private:
15
         int geschw;
16
         int x,y,z;
17
18
         reifen r1;
19
         reifen r2;
20
         reifen r3;
21
         reifen r4;
22
}

Wird die Klasse reifen denn sichtbar sein für Programmteile, die 
"auto.h" inkludieren?

von Sven B. (scummos)


Lesenswert?

1
class Auto {
2
  // ...
3
  private:
4
    class Reifen {
5
6
  };
7
};

von icke (Gast)


Lesenswert?

Ja, aber es wird nicht kompilieren:
1. "auto" ist ein geschützter Begriff.
2. Ich hatte das Beispiel nicht richtig angeschaut. Die forward 
declaration funktioniert nur, wenn du als Klassen-Member Pointer auf 
reifen* benutzt.

von Klops (Gast)


Lesenswert?

Axel471 schrieb:
> Wenn ich nun irgendwo im Hauptprogramm "Auto.h" inkludiere, dann sollen
> nur die public-Funktionen verwendbar sein. Aber ich inkludiere ja
> "reifen.h" gleich mit, d.h. dass im Hauptprogramm auch Reifen
> instantiiert werden können, die sollen aber verborgen sein.

Das sind aber zwei verschiedene Dinge ... Die privaten Member von "auto" 
(BTW: Bitte nicht wirklich diesen Namen verwenden ...) sind ja trotzdem 
nur klassenintern verwendbar - da kann der Benutzer so viele Reifen 
erzeugen, wie er will.

Axel471 schrieb:
> So etwa?

Nicht direkt, das funktioniert so (Vorausdeklaration) nur mit Zeigern 
und Referenzen, da der Compiler sonst die Größe des Typs "reifen" kennen 
muss und du damit wieder da bist, wo du angefangen hast.
Alternativ: Suche mal nach "PIMPL".

von Sven B. (scummos)


Lesenswert?

Oder du machst den Konstruktur private und deklarierst die eine Klasse 
als friend von der anderen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Würdest Du "reifen" als Pointer verwenden, würde eine 
Vorwärtsdeklaration von "reifen" genügen, auch wenn Du ein Objekt vom 
Typ NichtAuto instanziierst. Wenn Du aber "reifen" so verwendest, wie in 
Deinem Beispiel, muss für das Instanziieren eines Objekts vom Typ 
NichtAuto auch "reifen" bekannt sein, da andernfalls die Größe von 
NichtAuto nicht bekannt ist.

von Axel471 (Gast)


Lesenswert?

Danke für die Hilfe.

"pimple" gefällt mir gut. Nur dass man ein mal dynamisch Speicher 
allokieren muss ist suboptimal, aber man kann nicht alles haben.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Axel471 schrieb:
> allokieren muss ist suboptimal, aber man kann nicht alles haben.

Doch, guck Dir mal die Antwort von Sven B. richtig an.

von Sven B. (scummos)


Lesenswert?

Das ist aber kein PIMPL. ;)

Der Sinn von PIMPL ist ja schon auch ein bisschen, dass man 
Binärkompatibilität wahrt wenn man zum Beispiel Klassenmember hinzufügt 
oder so. Dazu muss man natürlich dynamische Speicherverwaltung nutzen.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Sven B. schrieb:
> Das ist aber kein PIMPL. ;)

Die ursprüngliche Aufgabenstellung war:

> d.h. dass im Hauptprogramm auch Reifen
> instantiiert werden können, die sollen aber verborgen sein.

dazu braucht man kein pimpl.
1
class Auto
2
{
3
public:
4
    auto();
5
6
    int geschw() const;
7
    int ort_x() const;
8
    int ort_y() const;
9
    int ort_x() const;
10
11
private:
12
    int geschw;
13
    int x,y,z;
14
15
    class reifen
16
    {
17
    ...
18
    };
19
20
    reifen r1;
21
    reifen r2;
22
    reifen r3;
23
    reifen r4;
24
};

Look Ma! No pimpl! ;-)

von Gerd E. (robberknight)


Lesenswert?

Torsten R. schrieb:
>
1
> class Auto
2
> {
3
[...]
4
> private:
5
[...]
6
>     class reifen
7
>     {
8
>     ...
9
>     };
10
>

Das löst zwar das, was der TO oben als Problem beschrieben hat. Aber es 
dürfte oft zu kurz gesprungen sein, da ich jetzt die class reifen bei 
class fahrrad, class schubkarre,... jeweils wieder neu erfinden muss.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Gerd E. schrieb:

> Aber es
> dürfte oft zu kurz gesprungen sein, da ich jetzt die class reifen bei
> class fahrrad, class schubkarre,... jeweils wieder neu erfinden muss.

Ja, genau so oft, wie Auto- und Rad-Klassen halt in der Praxis 
tatsächlich verwendet werden ;-)

Ist halt ganz schwierig über mögliche Anforderungen an offensichtlich 
praxis-fernen Beispielen zu diskutieren ;-) Ich würde beim konkreten 
Beispiel auch nicht auf die Idee kommen, den Einsatz von "reifen" an 
anderer Stelle zu unterbinden.

von Rolf M. (rmagnus)


Lesenswert?

Gerd E. schrieb:
> Das löst zwar das, was der TO oben als Problem beschrieben hat. Aber es
> dürfte oft zu kurz gesprungen sein, da ich jetzt die class reifen bei
> class fahrrad, class schubkarre,... jeweils wieder neu erfinden muss.

Dann leitet man fahrrad und schubkarre von einer gemeinsamen Basisklasse 
fahrzeug ab und gibt der die Reifen. Man kann diese ja auch protected 
machen.
Allerdings verstehe ich die Ursprungsfrage nicht so ganz:

Axel471 schrieb:
> "reifen.h" in "auto.h" zu inkludieren, macht m.M.n. Sinn, aber wie
> struktiere ich es so, dass die Reifen verborgen bleiben?

Warum? Wenn ich einen Reifen instanziieren will, kann ich ja auch 
einfach selber reifen.h inkludieren. Anders gefragt: Was genau ist das 
Ziel und welches Szenario soll damit verhindert werden?

von cppler (Gast)


Lesenswert?

Verstehe das eigentliche Problem auch nicht wirklich.
Warum nicht von Reifen/Motor/Lenkrad usw. usf. erben ?
Dafür ist doch OOP da ?
Oder die passenden Klassen in eine
1
private
 Deklaration einbinden.
Sinn macht mehr wenn Du erbst und die Dinge die Du nutzen willst, wie 
Reifenluftdruck u.ä. in der Klasse Reifen
1
private
 deklarierst und einen passenden setter und getter programmierst.
Dann kann z.B. das Objekt Autocomputer den Luftdruck anzeigen während 
das Objekt Schubkarre das halt nicht braucht ...

von Tom (Gast)


Lesenswert?

Ein javaesker Ansatz wäre ein abstraktes Interface Auto (nur mit den 
relevanten Methoden und ohne Member) und eine simple factory, die ein 
richtiges AutoObjekt erstellt, aber einen Basiszeiger auf ein Auto 
liefert.

Car.h:
1
#ifndef _CAR_H_
2
#define _CAR_H_
3
4
class Car
5
{
6
public:
7
    virtual ~Car()
8
    {
9
    }
10
    virtual int geschw() const = 0;
11
};
12
13
#endif


RealCar.h:
1
#ifndef _REAL_CAR_H_
2
#define _REAL_CAR_H_
3
4
#include "Car.h"
5
#include "Tire.h"
6
7
class RealCar : public Car
8
{
9
private:
10
    RealCar();
11
    RealCar(const RealCar& other);
12
13
    Tire tire;
14
15
public:
16
    int geschw() const;
17
    friend class CarFactory;
18
};
19
20
#endif


RealCar.cpp:
1
#include "RealCar.h"
2
3
RealCar::RealCar()
4
{
5
}
6
7
int RealCar::geschw() const
8
{
9
    return 23 * tire.radius();
10
}


Tire.h:
1
#ifndef _TIRE_H_
2
#define _TIRE_H_
3
4
class Tire
5
{
6
public:
7
    int radius() const;
8
};
9
10
#endif


Tire.cpp:
1
#include "Tire.h"
2
3
int Tire::radius() const
4
{
5
    return 42;    
6
}


CarFactory.h:
1
#ifndef _CAR_FACTORY_H_
2
#define _CAR_FACTORY_H_
3
4
#include "Car.h"
5
6
class CarFactory
7
{
8
public:
9
    static Car* make_car();
10
};
11
12
#endif


CarFactory.cpp:
1
#include "CarFactory.h"
2
#include "Car.h"
3
#include "RealCar.h"
4
5
Car* CarFactory::make_car()
6
{
7
    RealCar* p = new RealCar;
8
    return p;
9
}


main.cpp:
1
#include "Car.h"
2
#include "CarFactory.h"
3
4
#include <iostream>
5
6
int main()
7
{
8
    Car* mycar = CarFactory::make_car();
9
    std::cout << "geschw ist " << mycar->geschw() << "\n";
10
    delete mycar;
11
12
    /* Tire foo;    kompiliert nicht */
13
14
    return 0;
15
}
In echt würde man statt roher Pointer sinnvollerweise irgendwelche Smart 
Pointer benutzen.

Ob das in diesem Fall den gigantischen Komplexitätsgewinn wert ist, ist 
sehr stark zu bezweifeln.  Sinnvoll ist das nur, wenn es mehrere 
Autoarten gibt und CarFactory irgendwie entscheidet, welches sie 
liefert:
1
if (outdoor.temperature() > 23.0)
2
    return new Cabrio;
3
else if (road.is_icy())
4
    return new Jeep;
5
else
6
    return new Opel;

von Mikro 7. (mikro77)


Lesenswert?

Axel471 schrieb:

> Wenn ich nun irgendwo im Hauptprogramm "Auto.h" inkludiere, dann sollen
> nur die public-Funktionen verwendbar sein. Aber ich inkludiere ja
> "reifen.h" gleich mit, d.h. dass im Hauptprogramm auch Reifen
> instantiiert werden können, die sollen aber verborgen sein.
>
> "reifen.h" in "auto.h" zu inkludieren, macht m.M.n. Sinn, aber wie
> struktiere ich es so, dass die Reifen verborgen bleiben?

Kurze Antwort: C++ ist auf Performance ausgelegt. Statt zu verpointern 
wird ein zusammenhängender Speicherbereich gewählt. Dem Anwender steht 
es natürlich trotzdem frei (wie Rufus Τ. Firefly bereits schrieb), 
selbst zu verpointern (und damit zu verbergen).

Etwas auführlich findest Du das bei Scott Meyers, bspw. hier online: 
http://debian.fmi.uni-sofia.bg/~mrpaff/Effective%20C++/EC/EI34.HTM 
(nicht vom Titel irritieren lassen).

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Tom schrieb:

> In echt würde man statt roher Pointer sinnvollerweise irgendwelche Smart
> Pointer benutzen.

Ja, dann zeig einem Anfänger doch nicht erst, wie man es nicht macht. 
;-)

Irgend welche Smart Pointer wäre bis C++11 std::auto_ptr und ab C++11 
std::unique_ptr (liegen jedem Compiler bei, gibt überhaupt keinen Grund, 
die nicht zu verwenden).

In C++ (und in C ist das glaube ich auch so), gilt: Bezeichner die mit 
zwei Unterstrichen, oder Bezeichner die mit einem Unterstrich beginnen, 
gefolgt von einem Großbuchstaben anfangen, gehören dem Compiler und 
dürfen von uns nicht verwendet werden.

von Rolf M. (rmagnus)


Lesenswert?

Torsten R. schrieb:
> Irgend welche Smart Pointer wäre bis C++11 std::auto_ptr und ab C++11
> std::unique_ptr (liegen jedem Compiler bei, gibt überhaupt keinen Grund,
> die nicht zu verwenden).

Naja, es gibt schon Gründe, std::auto_ptr in diesem Kontext nicht zu 
verwenden.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Rolf M. schrieb:
> Naja, es gibt schon Gründe, std::auto_ptr in diesem Kontext nicht zu
> verwenden.

Welche Gründe würdest Du sehen, bei einer Factory (der Kontext, den Tom 
vorgegeben hat) nicht std::auto_ptr zu verwenden? (vorrausgesetzt, die 4 
Jahre alte C++11 Version kann nicht verwendet werden) Sicher hat 
std::auto_ptr seine Macken, aber immer noch besser als nix.

von Karl H. (kbuchegg)


Lesenswert?

cppler schrieb:
> Verstehe das eigentliche Problem auch nicht wirklich.
> Warum nicht von Reifen/Motor/Lenkrad usw. usf. erben ?
> Dafür ist doch OOP da ?

Das ist meistens keine gute Idee.

Halte dich beim (public) Vererben an die einfache Regel, dass eine 
derartige Vererbung eine "Ist ein" Beziehung ausdrueckt.
Frag dich also einfach mal, ob ein Auto (auch im weitesten Sinne) eine 
Form eines Reifens ist. Wenn die Antwort Nein lautet, dann ist Vererbung 
in der ueberwiegenden Mehrzahl der Fälle keine gute Idee.
Wenn du draufkommst, dass du eine "Hat ein" Beziehung beschreiben 
willst, dann ist die Einführung einer Klassen-Member Variablen das 
Mittel der Wahl

von Benji (Gast)


Lesenswert?

Ich denke mal der TO will einfach Klassen-Internas verbergen.

Ich hatte z.B. mal eine Klasse die eine Serielle Verbindung verwaltet 
erstellt.
Diese benutzt intern ganz oldschool termios.h.
Die daraus resultierenden Membervariablen wollte ich auch vom Benutzer 
verstecken.
Ebenso die benutzte Ringpufferklasse.

Man mag ja gerne die konkrete Implementierung hinter einem statischen 
Interface verbergen, das gleich bleibt auch wenn sich Internas ändern.

von cppler (Gast)


Lesenswert?

Karl H. schrieb:
> cppler schrieb:
>> Verstehe das eigentliche Problem auch nicht wirklich.
>> Warum nicht von Reifen/Motor/Lenkrad usw. usf. erben ?
>> Dafür ist doch OOP da ?
>
> Das ist meistens keine gute Idee.
>
> Halte dich beim (public) Vererben an die einfache Regel, dass eine
> derartige Vererbung eine "Ist ein" Beziehung ausdrueckt.
> Frag dich also einfach mal, ob ein Auto (auch im weitesten Sinne) eine
> Form eines Reifens ist. Wenn die Antwort Nein lautet, dann ist Vererbung
> in der ueberwiegenden Mehrzahl der Fälle keine gute Idee.
> Wenn du draufkommst, dass du eine "Hat ein" Beziehung beschreiben
> willst, dann ist die Einführung einer Klassen-Member Variablen das
> Mittel der Wahl

Hatte ich das nicht auch in Erwägung gezogen oder habe ich mich falsch 
ausgedrückt ?
Ich würds aber trotzdem so machen weil ich da mehr Flexibiltät habe, 
auch wenn es wie Du schreibst ein Dilemma aufwirft.
Wie würdest Du das denn in z.B. UML darstellen ?
Ist halt wieder die Frage ob das Rad vor dem Ei "erfunden" wurde ;-)
Aber Du schreibst ja "meistens" ;-)
OOP ist nicht so einfach und es gibt viele Wege nach Rom, einer ist was 
ich geschrieben habe.
Und warum bin ich noch nicht inner Heia ?
Zuviel Kaffee kann schonmal zu irgendwas führen ...

von bal (Gast)


Lesenswert?

cppler schrieb:
> OOP ist nicht so einfach und es gibt viele Wege nach Rom,

In dem Fall nicht. KHB hat schon recht.
In deinem Beispiel handelt es sich um eine Ist-Teil-von-Beziehung, da 
ist Vererbung völlig fehl am Platz.

cppler schrieb:
> Wie würdest Du das denn in z.B. UML darstellen ?

In UML ist diese Art der Beziehung ganz genau definiert. Stichwort: 
Komposition.

Klar, man kann auch alles von jedem erben lassen. Klappen wirds schon 
irgendwie...

von Klops (Gast)


Lesenswert?

cppler schrieb:
> Ich würds aber trotzdem so machen weil ich da mehr Flexibiltät habe,

In welcher Hinsicht? Das mit der Darstellung in UML verstehe ich auch 
nicht. Man kann Komposition, Aggregation, Ableitung und mehr darstellen.

cppler schrieb:
> Warum nicht von Reifen/Motor/Lenkrad usw. usf. erben ?

Weil es sowohl vom OO-Design her als auch aus technischen Gründen eine 
ausgesprochen schlechte Idee ist.

von Tom (Gast)


Lesenswert?

cppler schrieb:
> Warum nicht von Reifen/Motor/Lenkrad usw. usf. erben ?
Ist der Beitrag Satire?

bal schrieb:
> Klar, man kann auch alles von jedem erben lassen.

;)
Auto erbt dann viermal von Reifen. Mist, geht nicht, also anders:
1
class ReifenVL
2
{
3
    // void pumpen(); mist, das waere spaeter nicht eindeutig, also anders:
4
    void pumpen_vl();
5
};
6
7
class ReifenVR
8
{
9
    void pumpen_vr();
10
};
11
12
class ReifenHL
13
{
14
    void pumpen_hl();
15
};
16
17
class ReifenHR
18
{
19
    void pumpen_hr();
20
};
21
22
class Auto: public ReifenVL, public ReifenVR, public ReifenHL, public ReifenHR, public Motor, public Lenkrad
23
{
24
};
So macht man flexible SW-Architektur richtig.

von Karl H. (kbuchegg)


Lesenswert?

cppler schrieb:

> Ich würds aber trotzdem so machen weil ich da mehr Flexibiltät habe,
> auch wenn es wie Du schreibst ein Dilemma aufwirft.

Das ergibt dann genau die Programme, die keiner warten will und 
deretwegen C++ einen schlechten Ruf hat. Dabei ist gerade dieser Teil 
des Hierarchiedesigns relativ simpel und straigth forward. Hält man sich 
daran, ergibt das Klassenhierarchien die leicht zu durchschauen, leicht 
zu verwenden und leicht zu ändern sind. Hält man sich nicht daran, artet 
das über kurz oder lang in einen Krampf aus.
Ein PKW ist nun mal kein Lenkrad und ein PKW ist kein Motor. Ein PKW 
ist auch keine Windschutzscheibe und es ist auch kein Blinker. Aber 
es hat all diese Dinge.
Allerdings ist ein PKW ein Kraftfahrzeug. Und ein Kraftfahrzeug ist 
ein Fahrzeug dessen Merkmal darin besteht, dass ein Kraftfahrzeug per 
Definition einen Motor hat. Auch ein LKW ist ein Kraftfahrzeug. Da 
ein Kraftfahrzeug über einen Motor verfügt, folgt daraus automatisch, 
dass auch ein LKW einen Motor hat. Womit auch klar gestellt ist, dass 
der Motor zum Kraftfahrzeug gehört, wenn man in seiner Modellierung die 
Hierarchie bis mindestens zum Kraftfahrzeug oder noch weiter hinauf 
modellieren muss, weil man auch Schiffe und Flugzeuge modellieren 
möchte.
Womit allerdings noch lange nicht gesagt ist, welcher Art dieser Motor 
ist. Ein Kraftfahrzeug hat einen. Punkt. Konkret kann das ein Benziner 
oder ein Dieselmotor sein. Das ist wiederrum dem Kraftfahrzeug egal, es 
hält einfach nur einen Pointer auf den Motor (muss ein Pointer sein, 
damit virtuelle Methodenaufrufe funktionieren). Das Kraftfahrzeug 
startet einfach nur den Motor. Wie das konkret geht, dass weiss dann 
jeder Motortyp für sich selbst, das hat das Kraftfahrzeug nicht zu 
interessieren.
Kommt dann allgemein ein mit Erdgas betriebener Motor zur Flotte hinzu, 
dann genügt es, einen entsprechende Klasse von der Motor-Klasse 
herzuleiten und die 'Start' Methode zu definieren. An den 
Kraftfahrzeugen ändert sich genau gar nichts. Die rufen weiterhin 
einfach nur die Start-Methode auf. Denn wie das genau geht, das weiss ja 
jeder Motor für sich selbst. Der Dieselmotor wird seine Vorglühkerzen 
aktivieren, während der Benziner die Benzinpumpe einschaltet und ein 
Elektromotor gar nichts tun muss.

: Bearbeitet durch User
von beric (Gast)


Lesenswert?

Tom schrieb:
> class Auto: public ReifenVL, public ReifenVR, public ReifenHL, public
> ReifenHR, public Motor, public Lenkrad
> {
> };
> So macht man flexible SW-Architektur richtig.

Hm, kein Reserverad? Dann bitte alle Reifen von RunFlats ableiten!

von beric (Gast)


Lesenswert?

Karl H. schrieb:
> ...
> Womit auch klar gestellt ist, dass der
> Motor zum Kraftfahrzeug gehört, wenn man in seiner Modellierung die
> Hierarchie bis mindestens zum Kraftfahrzeug oder noch weiter hinauf
> modellieren muss, weil man auch Schiffe und Flugzeuge modellieren
> möchte.
> Womit allerdings noch lange nicht gesagt ist, welcher Art dieser Motor
> ist. Ein Kraftfahrzeug hat einen. Punkt.

Hm, eher Semikolon. Ein Kraftfahrzeug hat mindestens einen, würde ich 
eher sagen. Sonst stehen alle Toyota Prius und Opel Ampera dumm da.

von Karl H. (kbuchegg)


Lesenswert?

beric schrieb:
> Karl H. schrieb:
>> ...
>> Womit auch klar gestellt ist, dass der
>> Motor zum Kraftfahrzeug gehört, wenn man in seiner Modellierung die
>> Hierarchie bis mindestens zum Kraftfahrzeug oder noch weiter hinauf
>> modellieren muss, weil man auch Schiffe und Flugzeuge modellieren
>> möchte.
>> Womit allerdings noch lange nicht gesagt ist, welcher Art dieser Motor
>> ist. Ein Kraftfahrzeug hat einen. Punkt.
>
> Hm, eher Semikolon. Ein Kraftfahrzeug hat mindestens einen, würde ich
> eher sagen. Sonst stehen alle Toyota Prius und Opel Ampera dumm da.

Es sei denn du führst einen Motortyp 'Hybrid' ein, der aus dem 
entsprechenden Management und 2 weiteren Motoren besteht :-)

ABer du hast schon recht. Man sollte dann nicht mehr davon sprechen, 
dass ein Kraftfahrzeug einen Motor hat, sondern es hat einen Antrieb.

Lässt sich alles modellieren, wenn es denn sein muss.
Aber Ausgangspunkt ist ist die Unterscheidung 'ist ein' und 'hat ein' 
und wie man diese Beziehungen in den meisten Fällen sinnvoll im 
Hierarchiedesign unterbringt.

Interssant wäre zb auch die Fragestellung, ob ein Fahrrad ein 
Kraftfahrzeug darstellt mit einem Antriebstyp 'Mensch'. Bzw. ein 
Hybridantrieb, der die beiden Antriebe 'elektrisch' und 'Mensch' 
zusammenfasst - ein E-Bike.
Hmm. Die Hierarchie scheint so gut zu funktionieren und das ist immer 
ein gutes Zeichen, wenn sich auch Dinge modellieren lassen (mglw. mit 1 
oder 2 zusätzlichen Klassen, die nahtlos ins Design passen und auch 
nachträglich mit wenig Problemen einschieben lassen), an die man vorher 
gar nicht gedacht hat und ohne dass man 70% des ganzen Programms umbauen 
muss.

: Bearbeitet durch User
von Tom (Gast)


Lesenswert?

Karl H. schrieb:
> Interssant wäre zb auch die Fragestellung, ob ein Fahrrad ein
> Kraftfahrzeug darstellt mit einem Antriebstyp 'Mensch'.

Dann wird es langsam relevant, was man von dem Modell eigentlich will. 
Die ganze Realität ist zu komplex zum Modellieren.

Wenn ich Leisure Suit Larry 17 programmiere, erfüllt ein Fahrzeug andere 
Aufgaben¹ als bei einem Tool, das die gleichzeitigen Reisen von 10000 
Vertretern optimiert auf den vorhandenen Fuhrpark und andere 
Verkehrsmittel verteilt². In beiden Fällen interessiert mich der Motor 
überhaupt nicht. Anders bei einem Rennsimulatorspiel, bei dem man ein 
Fahrzeug aus Komponenten zusammenstellen kann. Oder einem 
Autoquartettgenerator. Oder einem Tool, das Benzinpreise unter 
Berücksichtigung der Urlaubswellen und Staumeldungen zentral optimiert.
In allen Fällen wird eine Klasse "Fahrzeug" völlig anders aussehen; in 
keinem Fall wird sie aus Motor und 4 Rädern bestehen.


Nichtwissen macht frei und flexibel. Wenn der Vertreterplaner nur mit 
generischen Transportmitteln² arbeitet, von deren innerer Funktion und 
Komponenten er nichts weiß, kann ich dem Algorithmus in der übernächsten 
Version ein Beamgerät unterschieben, ohne etwas zu ändern. Und Larry 
kann in Teil 523 ohne große Änderungen mit einem Hoverboard oder einem 
Spacepony (beides von ¹ abgeleitet) vor der Disko auftauchen.
1
// ¹
2
class IStatusSymbol
3
{
4
public:  
5
    virtual int get_status_points() = 0;
6
};
7
8
// ²
9
class ITransportationDevice
10
{
11
public:
12
    virtual void transport(Person& person, const Location& start, const Location& destination) = 0;
13
};

von Tom (Gast)


Lesenswert?

beric schrieb:
> Hm, kein Reserverad? Dann bitte alle Reifen von RunFlats ableiten!

Gegenvorschlag: Jede Reifenklasse bekommt ein Feld mit einem Status-enum 
{OK, PLATT, GEKLAUT, IST_EIN_RESERVERAD}. Dazu gibt es einen globalen 
ReifenManager (natürlich ein Singleton), der das alles verwaltet und der 
sich auch merkt, ob noch ein Reserverad im Kofferraum ist. Das ist 
flexibler.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.