Abstrakte Klasse durch Initlasisierungsliste referenzieren

Gast #5982888
Lesenswert?

Ich muss für ein STM32 Microcontroller Projekt in C++ ein Objekt einer 
Klasse durch Referenz aufrufen, dass ein Interface initialisiert.
Das Problem ist dass das Objekt während der Runtime gebraucht wird aber 
es da noch nicht existiert.

Ich habe es mit constexpr versucht aber das scheint nicht zu 
funktionieren.

Die Klasse nennt sich Ltdc und das Objekt muss den Konstruktor aufrufen, 
zB LtdcObjekt(Ldtc()),


class Ltdc : public ILtdc
{
      public:
        constexpr Ltdc() noexcept {};
}


///////////////////////////////////////

class ILtdc
{
    protected:

    constexpr ILtdc() { }

    public:

    virtual ~ILtdc() {};
}
///////////////////////////////////////

class Ili9341 final
{
  public:

  Ili9341() noexcept;

  ILtdc & ltdc; //Interface Ltdc Referenz
}


///////////////////////////////////////

Ili9341:: Ili9341() noexcept :

    ltdc(Ltdc()), //Hier wird es in der cpp Datei aufgerugen
{ }


////////////////////////////////////////

Dieser Fehler wird mir geworden

error: #461 initial value of non-const must be an lvalue
#5982908
Lesenswert?

Evil-E schrieb:
> Ich muss für ein STM32 Microcontroller Projekt in C++ ein Objekt einer
> Klasse durch Referenz aufrufen, dass ein Interface initialisiert.
> Das Problem ist dass das Objekt während der Runtime gebraucht wird aber
> es da noch nicht existiert.
>
> Ich habe es mit constexpr versucht aber das scheint nicht zu
> funktionieren.

Hat damit auch nichts zu tun.


> Ili9341:: Ili9341() noexcept :
>
>     ltdc(Ltdc()), //Hier wird es in der cpp Datei aufgerugen
> { }
>
>
> ////////////////////////////////////////
>
> Dieser Fehler wird mir geworden
>
> error: #461 initial value of non-const must be an lvalue

Du versuchst eine lvalue-reference durch ein rvalue zu initialisieren. 
Das geht nicht.
Gast #5982925
Lesenswert?

Das Problem ist die Zeile:
1
    ltdc(Ltdc()), //Hier wird es in der cpp Datei aufgerugen

Da wird versucht, ein anonymes Object (rvalue) an eine Lvalue-Referenz 
zu binden. Das ist verboten, da das anonyme Objekt mit Verlassen des 
Konstruktors (genauer: der Initialisierungsliste) automatisch zerstört 
wird und man dann eine "hängene" (ungültige, tote) Referenz 
zurückbehält.

Achtung! Mit einem Zeiger anstelle einer Referenz würde das nicht besser 
werden!

Mögliche Lösung (ohne Änderung/Verbesserung des Klassendesigns):
Speichern einer dynamisch erzeugten Instanz, z.B. mittels 
std::unique_ptr.
Der std::unique_ptr sorgt dann automatisch auch für die Zerstörung des 
verwaltenen Objekts im Destruktor.
1
#include <memory>
2

3
class ILtdc
4
{
5
protected:
6
    constexpr ILtdc() { }
7

8
public:
9
    virtual ~ILtdc() {};
10
};
11

12
///////////////////////////////////////
13

14
class Ltdc : public ILtdc
15
{
16
public:
17
    constexpr Ltdc() noexcept {};
18
};
19

20
///////////////////////////////////////
21

22
class Ili9341 final
23
{
24
public:
25
  Ili9341() noexcept;
26
  std::unique_ptr<ILtdc> ltdc; //Interface Ltdc Referenz
27
};
28

29
///////////////////////////////////////
30

31
Ili9341::Ili9341() noexcept
32
: ltdc(std::make_unique<Ltdc>()) //Hier wird es in der cpp Datei aufgerugen
33
{
34
}

Das Member 'ltdc' kann dann wie ein Zeiger dereferenziert werden.
Gast #5982941
Lesenswert?

Evil-E schrieb:
> Wir sind im Embedded Bereich und haben leider keinen Zugriff auf externe
> Bibliotheken, darunter auch die std Bibliothek.

Hmm, dann gibt es (wahrscheinlich) für das Target auch kein new/delete, 
somit sehe ich als Option nur das direkte Speichern einer Instanz der 
Implementierungsklasse (class Ltdc) als Datenmember in der Klasse 
Ili9341 (oder irgendwo anders).
1
class ILtdc
2
{
3
protected:
4
    constexpr ILtdc() { }
5

6
public:
7
    virtual ~ILtdc() {};
8
};
9

10
///////////////////////////////////////
11

12
class Ltdc : public ILtdc
13
{
14
public:
15
    constexpr Ltdc() noexcept {};
16
};
17

18
///////////////////////////////////////
19

20
class Ili9341 final
21
{
22
public:
23
  Ili9341() noexcept;
24
  Ltdc ltdc; //Interface Ltdc Referenz
25
};
26

27
///////////////////////////////////////
28

29
Ili9341::Ili9341() noexcept
30
: ltdc() //Hier wird es in der cpp Datei aufgerugen
31
{
32
}
Gast #5982946
Lesenswert?

Wahrscheinlich soll die Ili9341 Klasse doch gar nicht wissen, welche 
ILtdc Implementation da jetzt benutzt wird. Sonst wäre die abstrakte 
Klasse ziemlich nutzlos. Daher sollte man die Instanz außerhalb anlegen 
und übergeben:
1
class Ili9341 final
2
{
3
  public:
4

5
  Ili9341(ILtdc & l) noexcept;
6

7
  ILtdc & ltdc; //Interface Ltdc Referenz
8
}
9

10

11
///////////////////////////////////////
12

13
Ili9341:: Ili9341(ILtdc & l) noexcept :
14

15
    ltdc(l), // Referenz übernehmen
16
{ }

und dann, typischerweise als globale Variablen:
1
Ltdc ltdc;
2
Ili9341 ili9341 (ltdc);

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