Moin,
ich habe eine Reifen-Klasse und verschiedene Fahrzeugklassen. Jedes
Fahrzeug kann unterschiedlich viel Reifen haben, die Anzahl der Reifen
desselben Fahrzeugtyps ändert sich aber nie. Im folgenden ist der
"Pseudecode", den ich so in C++ aber nicht umgesetzt bekomme; Das
Befüllen des Reifenarrays in der abgeleiteten Klasse geht so nicht.
Hätte jemand eine Idee wie man das umsetzen kann?
Wernder
1
classReifen{
2
public:
3
Reifen(intbreite){}
4
};
5
6
classFahrzeug{
7
private:
8
Reifenreifen[];
9
};
10
11
classAuto:publicFahrzeug{
12
public:
13
Auto():reifen({100,100,120,120})//hier sollen die 4 Reifenobjekte erzeugt werden
Erstens kann man in der abgeleiteten Klasse nicht direkt auf private
member der Basisklasse zugreifen.
Zweitens muss die Größe des Arrays fixiert werden (zur
Übersetzungszeit), der Compiler muss wissen, wie groß das Objekt ist.
Unter diesen Voraussetzungen gehts ab C++11, man muss aber
{}-initializer verwenden.
Ja, muss natürlich protected sein. C++11 steht leider nicht zur
Verfügung :-(
>Zweitens muss die Größe des Arrays fixiert werden (zur>Übersetzungszeit), der Compiler muss wissen, wie groß das Objekt ist.
Es muss eben je nach Klasse unterschiedlich groß sein (z.B. Auto 4,
Fahrrad 2). Da das in C++ so nicht geht suche ich nach einem anderen
Konzept. Zusätzlich handelt es sich noch dazu um einen älteren Keil
(µVision4) für eine Embedded Platform, so dass die STL auch nicht zur
Verfügung steht.
Werner
Wenns in jeder abgeleiteten Klasse unterschiedlich gross ist, dann muss
das Array in der abgeleiteten Klasse deklariert werden, oder man erbt
von einer template-basis-klasse, die man mit der größe des arrays
spezialisiert, aber vermutlich geht das mit dem compiler nicht.
Die Elemente des Arrays kann man einzeln explizit initialisieren, bläht
den Text halt a bissl auf, codesize sollte gleich bleiben. IIRC gibts da
ein boost-ding was einem die Arbeit abnimmt, von dessen impl könnte man
sich inspirieren lassen.
warum muss es denn ein Array sein - C++ bietet auch Vektor, List und
ähnliches an. Dann kann die Größe zur Laufzeit festgelegt werden.
ein Array könnte man auch dynamische allokieren.
Peter II schrieb:> warum muss es denn ein Array sein - C++ bietet auch Vektor, List> und ähnliches an.>> die STL auch nicht zur Verfügung steht
Allerdings ist "PC-Programmierung" das falsche Unterforum für die Frage
(der TO hätte zumindest die C++-Version und die Restriktionen gleich
erwähnen sollen).
Werner schrieb:> Geht das so?
nein.
Denn ein Objekt von einen Type brauch auch eine definierte Größe.
was soll denn sizeof( Fahrrad ) liefern?
Man könnte es mit Templates lösen.
>statt>Fahrrad(): reifen(Reifen(10), Reifen(20)) {}>Fahrrad(): reifen{Reifen(10), Reifen(20)}{}
Also kompilierbares Beispiel:
1
classReifen{
2
public:
3
Reifen(intbreite){}
4
};
5
6
classFahrrad{
7
private:
8
Reifenreifen[2];
9
public:
10
Fahrrad():reifen{(10),(10)}{}
11
};
Ärgerlich, das geht z. B. mit dem g++ 7.1.1 wunderbar, aber der olle
Keil 4 sagt (selber Code!) zur Zeile mit dem Fahrrad-Ctor:
error: expected a declaration
error: expected a "("
error: no default constructor exists for class "Reifen"
warning: expression has no effect
warning: expression has no effect
error: expected a ";"
>Man könnte es mit Templates lösen.
Du meinste die Arraygröße über ein Template festlegen? Ja, beim obigen
Fahrrad habe ich ja schon ein Array fester Größe, aber der Keil
kompiliert das nicht :-(
Werner
Wenn es nicht so richtig will, warum mit dem Kopf durch die Wand?
Du must es ja nicht über die Init Liste machen. Weise den Variablen
einfach den wert im Ctor zu.
>Wenn es nicht so richtig will, warum mit dem Kopf durch die Wand?
Ja warscheinlich muss ich es so machen :-( :-( Schade, wäre anders
deutlich kompakter geworden...
Werner
cbe schrieb:> reifen = (Reifen*)malloc(sizeof(Reifen[4]));> for(int i = 0; i < 4; ++i)> new (&reifen[i]) Reifen(245);
Sorry, aber malloc und new zu mischen ist Gewurschtel.
ruft nur den Konstruktor auf &reifen[i] auf. Es wird kein Speicher
allokiert.
Speicher mit new holen und mit free freigeben, bzw. mit malloc holen und
mir delete freigeben ist in der Tat Unfug. Den Fall haben wir hier aber
nicht.
Sebastian E. schrieb:> ruft nur den Konstruktor auf &reifen[i] auf. Es wird kein Speicher> allokiert.
Es bleibt aber trozdem dabei, dass
Rufus Τ. F. schrieb:> Sorry, aber malloc und new zu mischen ist Gewurschtel.
Richtig ist. In C++ nimmt man new und kein malloc. Das ist schlich nicht
nötig. Eigentlich benutzt man new auch nicht nicht mehr seit C++14.
Dafür gibts Smartpointer.
Der C++ Weg wäre einen enprechenden Container zu nehmen.
1
std::vector<Reifen>reifen;
2
3
for(autoi:{20,30})
4
reifen.push_back(i)
damig. Darf ja kein modernes C++ sein. Dann also mit einer normalen for
Schleife (die Mühe sie zu schreiben mache ich mal nicht).
cbe schrieb:> reifen = (Reifen*)malloc(sizeof(Reifen[4]));> for(int i = 0; i < 4; ++i)> new (&reifen[i]) Reifen(245);> }
Warum denn malloc und placement new statt einfach normales new?
nicht"Gast" schrieb:> Der C++ Weg wäre einen enprechenden Container zu nehmen.> std::vector<Reifen> reifen;>> for (auto i: {20,30})> reifen.push_back(i)
Warum dann nicht gleich:
1
std::vector<Reifen>reifen{20,30};
?
> damig. Darf ja kein modernes C++ sein.
Und keine Standardlib.
> Dann also mit einer normalen for Schleife (die Mühe sie zu schreiben> mache ich mal nicht).
Und ohne vector. Damit sind wir wieder beim new.
Rolf M. schrieb:> Warum denn malloc und placement new statt einfach normales new?
Dann eben nur new.
1
classFahrzeug{
2
protected:
3
Reifen**reifen;
4
};
5
6
classAuto:publicFahrzeug{
7
public:
8
Auto(){
9
reifen=newReifen*[4];
10
for(inti=0;i<4;++i)
11
newReifen(245);
12
}
13
~Auto(){
14
for(inti=0;i<4;++i){
15
deletereifen[i];
16
}
17
deletereifen;
18
}
19
};
In der Variante ist IMHO auch am nähesten an der Probelmstellung des TO.
Also für Versionen < C++11 und ohne STL finde ich die Lösung gar nicht
mal so schlecht.
Wobei mir persönlich die Version mit malloc und placement new besser
gefallen hat, da alle 4 Instanzen direkt hintereinander liegen - also
wie im Array des TO, nur eben erzeugt mit nicht Standartkonstruktoren.
Rufus Τ. F. schrieb:> Sorry, aber malloc und new zu mischen ist Gewurschtel.
Statt malloc könnte man den Speicher natürlich auch mit new
allokieren...
>Es geht auch ohne new oder malloc, wenn man Platz für einen Pointer>verschwenden kann.
Da motzt der Compiler, weil es keinen Standardkonstruktor für Reifen
gibt, man müsste die Reifen schon in der Initialisierungsliste (nach dem
Doppelpunkt) des Konstruktors setzen...
Werner