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
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.
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.
Wir sind im Embedded Bereich und haben leider keinen Zugriff auf externe Bibliotheken, darunter auch die std Bibliothek.
Dein Code von oben macht ja auch so, wie er da steht, keinen Sinn. Denn die offensichtliche Laufzeitpolymorphie benötigst Du ja gar nicht. Ein einfaches Datenelement wäre ja ausreichend.
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 | }
|
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); |
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.