C++ Objektarray im Konstruktor initialisieren?

Gast #5135188
Lesenswert?

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
class Reifen {
2
public:
3
    Reifen(int breite) {}
4
};
5

6
class Fahrzeug {
7
private:
8
    Reifen reifen[];
9
};
10

11
class Auto: public Fahrzeug {
12
public:
13
    Auto(): reifen({100, 100, 120, 120}) //hier sollen die 4 Reifenobjekte erzeugt werden
14
};
Gast #5135202
Lesenswert?

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.
Gast #5135210
Lesenswert?

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
Gast #5135221
Lesenswert?

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.
Gast #5135373
Lesenswert?

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).
Gast #5135546
Lesenswert?

>Wenns in jeder abgeleiteten Klasse unterschiedlich gross ist, dann muss
>das Array in der abgeleiteten Klasse deklariert werden,

Dann folgende Idee:
1
class Fahrrad: public Fahrzeug {
2
private:
3
  Reifen reifen[2];
4
public:
5
  Fahrrad(): reifen(Reifen(10), Reifen(20)) {}
6
};

Geht das so? Wenn ja wie lautet die Syntax im Konstruktor um das 
reifen-array zu initialisieren?

Werner
Gast #5135657
Lesenswert?

>statt
>Fahrrad(): reifen(Reifen(10), Reifen(20)) {}
>Fahrrad(): reifen{Reifen(10), Reifen(20)}{}

Also kompilierbares Beispiel:
1
class Reifen {
2
public:
3
    Reifen(int breite) {}
4
};
5

6
class Fahrrad {
7
private:
8
    Reifen reifen[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
Gast #5135691
Lesenswert?

Ohne C++-11 könntest du dir so behelfen
1
class Reifen {
2
public:
3
    Reifen(int breite) {
4
    }
5
    ~Reifen() {
6
    }
7
};
8

9
class Fahrzeug {
10
protected:
11
    Reifen *reifen;
12
};
13

14
class Auto : public Fahrzeug {
15
public:
16
   Auto() {
17
      reifen = (Reifen*)malloc(sizeof(Reifen[4]));
18
      for(int i = 0; i < 4; ++i)
19
         new (&reifen[i]) Reifen(245);
20
   }
21
   ~Auto() {
22
      for(int i = 0; i < 4; ++i) {
23
         reifen[i].~Reifen();
24
      }
25
      free(reifen);
26
   }
27
};
Gast #5135692
Lesenswert?

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.
1
  class Fahrrad {
2
private:
3
    Reifen reifen[2];
4
public:
5
    Fahrrad() {
6
        reifen[0].breite = 10;
7
        reifen[1].breite = 20;
8
    }
9
};
Gast #5136011
Lesenswert?

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 (auto i: {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).
#5136272
Lesenswert?

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.
Gast #5136293
Lesenswert?

Rolf M. schrieb:
> Warum denn malloc und placement new statt einfach normales new?

Dann eben nur new.
1
class Fahrzeug {
2
protected:
3
    Reifen **reifen;
4
};
5

6
class Auto : public Fahrzeug {
7
public:
8
   Auto() {
9
      reifen = new Reifen*[4];
10
      for(int i = 0; i < 4; ++i)
11
         new Reifen(245);
12
   }
13
   ~Auto() {
14
      for(int i = 0; i < 4; ++i) {
15
         delete reifen[i];
16
      }
17
      delete reifen;
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...
Gast #5136323
Lesenswert?

Es geht auch ohne new oder malloc, wenn man Platz für einen Pointer 
verschwenden kann.
1
class Fahrzeug 
2
{
3
protected:
4
    Reifen* reifen;
5
};
6

7
class Auto : public Fahrzeug 
8
{
9
public:
10
   Auto() 
11
   {
12
      reifen = meine_reifen;
13
      for(int i = 0; i < 4; ++i)
14
          meine_reifen[i] = Reifen(245); // oder placement new
15
   }
16
private:
17
    Reifen meine_reifen[4];
18
};
Gast #5136813
Lesenswert?

>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
Beitrag #5137510 wurde von einem Moderator gelöscht.
Beitrag #5137741 wurde von einem Moderator gelöscht.
Beitrag #5137787 wurde von einem Moderator gelöscht.
Beitrag #5137832 wurde von einem Moderator gelöscht.
Beitrag #5137918 wurde von einem Moderator gelöscht.
Beitrag #5137936 wurde von einem Moderator gelöscht.
Beitrag #5137980 wurde von einem Moderator gelöscht.
Beitrag #5137981 wurde von einem Moderator gelöscht.
Beitrag #5138003 wurde von einem Moderator gelöscht.
Beitrag #5138083 wurde von einem Moderator gelöscht.
Beitrag #5138351 wurde von einem Moderator gelöscht.
Beitrag #5138521 wurde von einem Moderator gelöscht.
Beitrag #5139158 wurde von einem Moderator gelöscht.
Beitrag #5139160 wurde von einem Moderator gelöscht.
Beitrag #5139981 wurde von einem Moderator gelöscht.
Beitrag #5139984 wurde von einem Moderator gelöscht.
Beitrag #5140100 wurde von einem Moderator gelöscht.
Beitrag #5140185 wurde von einem Moderator gelöscht.
Beitrag #5140241 wurde von einem Moderator gelöscht.
Beitrag #5140382 wurde von einem Moderator gelöscht.
Beitrag #5142598 wurde von einem Moderator gelöscht.
Beitrag #5143772 wurde von einem Moderator gelöscht.
Beitrag #5144965 wurde von einem Moderator gelöscht.
Beitrag #5144997 wurde von einem Moderator gelöscht.
Beitrag #5145003 wurde von einem Moderator gelöscht.
Beitrag #5145233 wurde von einem Moderator gelöscht.
Beitrag #5145939 wurde von einem Moderator gelöscht.
Beitrag #5145964 wurde von einem Moderator gelöscht.
Beitrag #5148073 wurde von einem Moderator gelöscht.
Beitrag #5149299 wurde von einem Moderator gelöscht.
Beitrag #5149362 wurde von einem Moderator gelöscht.
Beitrag #5149383 wurde von einem Moderator gelöscht.
Beitrag #5149418 wurde von einem Moderator gelöscht.
Beitrag #5153245 wurde von einem Moderator gelöscht.
Beitrag #5167778 wurde von einem Moderator gelöscht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren