Hallo zusammen,
Ich möchte einen LED-String aus WS2812B ansteuern können.
Dazu habe ich einen Treiber der die Bits auf der HW Rausschreibt.
-->Funktioniert.
Eine Klasse RGB_LED, welche die eigenschaften(Farbe) der LED enthält.
-->Funktioniert.
Eine Klasse RGB_STRING welche eine Anzahl an RGB_LEDs enthalten soll.
Sie soll über einen Aufruf von write_to_string() die eigenschaften aller
LEDs an den String übertragen.
Weiterhin soll sie Farben, der LED nach Index einstellbar machen.
set_RGB_LED(uint8_t index, uint8_t red, uint8_t green, uint8_t blue)
Durch den Construktor soll ein Array mit zeigern auf die Elemente vom
Typ LED_String angelegt werden, durch welches die oben genannten
Funktionen von RGB_STRING durchitterieren können.
Hier leigt das Problem mit der Meldung:
Error : expected type-specifier before ';' token
In dieser Zeile:
RGB_STRING::string[i]=*new(RGB_LED());
Ich bin überfragt welchen Typ ich hier angeben soll.
Wäre schön wenn jemand eine idee hätte.
Weitere Fehler/Warungen gibt es nicht.
Hier der gesamte Code:
Du erzeugst eine RGB_LED Instanz auf dem Heap und übergibst deren
Adresse an ein "placement new", d.h. new soll an der übergebenen Adresse
eine Instanz des nach new(addr) folgende Typs erzeugen, also dessen
Konstruktor ausführen. Genau dieser Typ wird vermisst.
Daß du dieses Objekt nur kurz leben läßt, nämlich bis es vom Assignment
Operator in einen Slot deines Arrays kopiert wurde, ist zwar syntaktisch
korrekt, aber ungeschickt.
Generell: in der Implementierung einer Methode einer Klasse hat man
Zugriff auf die andern Member der Klasse, ohne den "Klassen-Namespace"
davorzuschreiben.
Hallo und vielen Dank,
so war es nicht gedacht, new soll nicht an der übergebenen Addresse ein
element des fehlenden Typs erzeugen.
Ich stelle es mit so vor, dass LED_STRING die zeiger auf die einzelnen
LEDs in string[] enthält.
Da ich die größe von String nicht fix festlegen möchte, soll sie
variabel sein. Nach Programmstart in String ein zeiger auf die
Basisaddresse eines Arrays von RGB_LED stehen.
Oh, ich habe nun eine Lösung gefunden :)
Hier meine Änderungen in RGB_STRING:
Es funktioniert bis auf einen kleinen BUG, wenn in main() keine farbe
gesetzt wird, bleiben die LEDs aus.
--> Folglich wird der Konstruktor nicht aufgerufen.
Wenn ich in den Konstruktor von RGB_String nach dem Anlegen der neuen
LED:
1
RGB_STRING::string[i*sizeof(RGB_LED)]->RGB_LED();
kommt die Meldung:
Error invalid use of 'RGB_LED::RGB_LED' Ver3_1_Atmega8
Bei
bekomme ich ein:
Error cannot call constructor 'RGB_LED::RGB_LED' directly
Wäre super wenn noch jemand wüsste warim die Klasse ohne
Konstruktoraufrif angelegt werden kann?
Denke ich korrekt, wenn ich davon ausgehe, dass die RGB_LED-Objekte nun
ab der basisaddresse des strings im Speicher liegen?
Grüße,
Matze
Matze schrieb:> so war es nicht gedacht, new soll nicht an der übergebenen Addresse ein> element des fehlenden Typs erzeugen.
Du nutzt hier aber placement new:
> RGB_STRING::string[i]=*new(RGB_LED());
Placement new sieht etwa so aus:
1
new(wert)Typ(Parameter);
Bei dir fehlt der Typ. Wenn du ein normales new willst, musst du die
Klammern weglassen.
Aber auch dann ergibt das alles so keinen Sinn. Du hast ein Element vom
Typ RGB_STRING, und nun erzeugst du ein neues dynamisches Objekt vom
gleichen Typ und weist das diesem Element zu. Den Zeiger auf das
dynamische Objekt verwirfst du dann und hast damit ein Memory-Leak.
Was mir noch auffällt:
RGB_STRING ist von RGB_LED abgeleitet. Warum?
Dem Array RGB_LED string[]; fehlt eine Größe.
Auch das ergibt in mehrererlei Hinsicht keinen Sinn:
> Bei> RGB_STRING::string[i*sizeof(RGB_LED)]->RGB_LED::RGB_LED();> bekomme ich ein:> Error cannot call constructor 'RGB_LED::RGB_LED' directly
Da hat der Compiler recht. Konstruktoren kann man nicht direkt aufrufen.
> Wäre super wenn noch jemand wüsste warim die Klasse ohne> Konstruktoraufrif angelegt werden kann?
Das weiß ich auch nicht. Da dem Array die Größe fehlt, hätte ich
erwartet, dass schon dort mit Fehler abgebrochen wird. Aber gcc lässt
das wohl als Erweiterung selbst im Standard-Modus durchgehen. Wie das
funktionieren soll, ist mir aber nicht klar.
Wenn das sauber funktionieren soll, wirst du nicht drum herum kommen,
ein paar Grundlagen von C++ zu lernen.
Da sind einige Ungereimtheiten, Undurchgängigkeiten und Lücken im
Grundlagenwissen zu finden. Anbei mein Vorschlag basierend auf dem, was
ich als gewünschte Funktionalität vermute. Nicht übermäßig schön, aber
funktionsfähig und der Heap wird dank Destruktor auf wieder freigegeben.
1
#include<memory>
2
3
classRGB_LED
4
{
5
public:
6
RGB_LED();
7
voidset_LED(void);
8
voidset_colors(uint8_tr,uint8_tg,uint8_tb);
9
private:
10
uint8_tred;
11
uint8_tgreen;
12
uint8_tblue;
13
};
14
15
16
17
RGB_LED::RGB_LED()
18
{
19
set_colors(0x00,0xff,0x00);
20
// sofern die LED jetzt bereits grün leuchten sollte:
RGB_LED*(*m_p_leds)[];// Pointer auf ein Array von Pointern auf RGB_LED
52
};
53
54
55
56
RGB_STRING::RGB_STRING(uint8_tled_cnt)
57
{
58
m_p_leds=(RGB_LED*(*)[])malloc(led_cnt*sizeof(RGB_LED*));// Speicher für Pointer-Array(RGB_LEDs) allokieren
59
m_led_cnt=led_cnt;
60
61
for(uint8_ti=0;i<m_led_cnt;i++){
62
(*m_p_leds)[i]=newRGB_LED;// RGB-LED auf Heap instanziieren und Adresse in Pointer-Array ablegen. new sorgt dafür, dass der Konstruktor aufgerufen wird.