Hallo,
folgende C++ Problematik:
Es existiert eine Template-Klasse List für verkettete Listen
1
template<classT>
2
classList
3
{
4
staticT*First;
5
staticT*Last;
6
T*Next;
7
// ...
8
}
Nun werden andere Objekte davon abgeleitet und bei deren Konstruktion
automatisch in der Liste verkettet. In diesem Fall sind es verschiedene
Treiberobjekte, die von List abgeleitet werden:
1
classGenericDriver:publicList<GenericDriver>
2
{
3
staticvoidInitAll(void);
4
staticvoidUpdateAll(void);
5
virtualvoidInit(void)=0;
6
virtualvoidUpdate(void)=0;
7
// ...
8
}
Das hat jetzt den Charme, dass man z.B. alle Treiber an einer Kette
durchlaufen kann, beispielsweise GenericDriver::InitAll(); aufruft und
alle Treiber initialisieren sich mit ihrer eigenen Init()-Funktion. Ein
weiteres Beispiel wäre der millisekündliche Aufruf von Update() über
UpdateAll();
Das Konzept ist soweit gut, funktioniert seit einigen Jahren prima.
Jetzt ergibt sich aber ein Problem:
Eine von GenericDriver abgeleitete Klasse, nennen wir sie
MySpecialDriver benötigt eine eigene Liste, die alle Instanzen von
MySpecialDriver verkettet aber die Basisklasse GenericDriver davon
unabhängig ja immer noch verkettet bleiben soll. Da die Basisklasse
GenericDriver ja bereits von List abgeleitet ist, kann ich die
MySpecialDriver nicht nochmal von List ableiten, sonst werden die
List-Anteile (Next-Pointer) von Basisklasse und abgeleiteter Klasse ja
"ambitious".
Wie könnte ich das elegant machen, dass ich das gleiche List-Template
verwende und dasselbe Treiberobjekt damit 2 unterschiedlichen und
voneinander unabhängigen verketteten Listen angehört?
Verwende die Liste nicht als Basisklasse, sondern nutze sie als
Member-Variable.
Ansonsten sieh Dir mal das Design-Pattern "Interfaces" an, damit kann
man solch eine alles-abarbeiten Logik auch wunderschön implementieren.
Allerdings eher generell: Du schreibst diesen Code für kleine MCUs?
Dabei finde ich Templates etc. eigentlich ganz schon oversized. Hast Du
Dir mal die entstehenden Code-Größen angesehen?
Ich finde C++ ist eine wundervolle, mächtige Sprache für die
Applikationsentwicklung auf Desktop-Rechnern, hat aber meiner Ansicht
nach in der embedded Entwicklung nur was zu suchen wenn man
a) genau weiß was man macht und welche Auswirkungen das hat und
b) eine MCU mit halbwegs Leistung zur verfügung har.
Hier auf Arbeit haben wir recht häufig Performanceprobleme, da
Firmwarekomponenten in (schlechtem) C++ geschrieben sind. Und hier
werkelt immerhin ein ARM9-Core @100Mhz...
Ja, dass C++ uU mehr Code produziert als C und man sich von der
PC-Progammierweise verabschieden muss ist mir klar. In diesem Fall macht
es aber durchaus Sinn und ist mehr die Ausnahme als die Regel. Der
Prozessor ist dick genug, auch Codegrößen und Speicherverbrauch stellen
kein Problem dar.
Danke für den Tipp mit den Interfaces, ich lese mich mal ein.
Alexander I. schrieb:> Es existiert eine Template-Klasse List für verkettete Listen [Beispiel]> Nun werden andere Objekte davon abgeleitet und bei deren Konstruktion> automatisch in der Liste verkettet.
Wenn du Objekte von einer Liste ableitest dann sind die abgeleiteten
Objekte auch Listen und werden nicht in irgendeine Liste eingehängt.
Irgendwie bist du auf dem falschen Dampfer.
Du hast 2 unabhängige Listen. Dann instanziiere die und hänge deine
Objekte einfach in die Liste(n) ein in die sie sollen.
für dich ist eine Liste und ein Element in der Liste dasselbe. Und genau
das ist dann der Punkt an dem dann meistens die Probleme anfangen.
Trenne die Dinge. Auf der einen Seite gibt es Listen und auf der anderen
Seite gibt es Knoten in der Liste. Das sind 2 verschiedene Dinge.
KHB:
Genau so ist es. Diese Listen-Implementierung ist recht speziell und
stammt nicht aus meiner Feder. Da die hier im Unternehmen aber zigfach
verwendet wird, versuche ich damit klarzukommen :-/
Udo:
Doch sie werden Listenelemente, weil im Konstruktor von List das neue
"List" automatisch verkettet wird. Die Liste an sich bleibt nur eine
Liste, da First und Last static sind. Ist eine sehr ungewöhnliche
Implementierung, ich weiß...
Alexander I. schrieb:> KHB:> Genau so ist es. Diese Listen-Implementierung ist recht speziell und> stammt nicht aus meiner Feder. Da die hier im Unternehmen aber zigfach> verwendet wird, versuche ich damit klarzukommen :-/
Dann solltest du das anleiern, dass das geändert wird.
Ist genauso wie die Unsitte, den Listeniterator in Form eines 'current'
Elements in die Liste selbst mit aufzunehmen. Das sieht auch auf den
ersten Blick ganz toll aus. Die Probleme kommen aber im Laufe der Zeit.
Hallo,
ich habe mir das jetzt genauer angeschaut, mich hatte der Name List auf
die falsche Fährte gebracht, weil ich hauptsächlich Jave programmiere
und da solche generischen Container per se zur Verfügung stehen.
Ich kann Karl Heinz nur zustimmern. Macht ein sauberes Design.
Eine Element ist ein Element und eine Liste eben eine Liste.
Wenn du verschiedene Treiber hast, dann leite die von einer Parentklasse
ab die eine Methode init() hat.
Dann erzeuge dir Listen vom Typ der Parentklasse und du kannst
unabhängig von der spezifischen Klasse des Treibers die Funktion init()
aufrufen.
Ich bin gerade dabei ein geößerer Codeteil hier komplett neu zu
designen, weil der ursprüngliche genau solche 'Abkürzungen' und
'Vereinfachungen' im Design gemacht hatte und jetzt bei der 3.
Erweiterung endgültig Schluss ist das noch dazuzufriemeln.
Also mach das was Karl Heinz sagt und designe es sauber.
Uli Trautenberg schrieb:> Deswegen als Member-Variablen definieren und nicht als Basisklasse...> class GenericDriver {>> static List<Type> statische_liste;> ...
Sorry aber für mich macht das wenig Sinn so.
Du willst eine Liste von Treibern..
jetzt definierst du eine Klasse Driver (Oder sogar Basisklasse weil das
Teil "Generic" heisst) und in der Klasse Treiber hast du als Attribut
die Liste. Weil du natürlich nicht in jeder Instanz eine eigene Liste
willst machst du sie statisch.
Für mich ist das von hinten durch die Brust ins Auge.
Ist das irgendein Designpattern das ich nicht kenne?
Udo Schmitt schrieb:> Ist das irgendein Designpattern das ich nicht kenne?
Das Design-pattern nennt sich "Ham'werImmerSoGemacht", auch bekannt als
"IstHaltSo,KannIchNixDrannÄndern".
Oliver
Oliver schrieb:> Das Design-pattern nennt sich "Ham'werImmerSoGemacht", auch bekannt als> "IstHaltSo,KannIchNixDrannÄndern".
:-)
Ach so ich glaube das heisst bei uns,
deswoarvor20johrschungut,alsoissesjetztahnochguut.
Schöne Grüße
Das ist eher eine philosophie-Frage. Ich würde die Liste unabhängig von
der eigentlichen Treiber-Klasse definieren, aber wenn sie schon
unbedingt mit reinmuß, dann als statischen Member.
Wenn man das Originalkonzept unbedingt und um jeden Preis halten muss,
dann ginge auch noch:
Eine 2.te Liste machen, der Daten aus Pointern zu den Knoten in der
ersten Liste besteht.
Karl Heinz Buchegger schrieb:> Wenn man das Originalkonzept unbedingt und um jeden Preis halten muss,> dann ginge auch noch:> Eine 2.te Liste machen, der Daten aus Pointern zu den Knoten in der> ersten Liste besteht.
Ich muss zurückrudern.
Ich glaube immer mehr, dass das ein schlechter Ansatz ist. Das Problem
besteht darin, dass man dann ganz schnell mit einer 2.ten Liste dasteht,
die Pointer auf Knoten enthält, die zb nicht mehr existieren.
Im Moment favorisiere ich eher einen anderen Ansatz:
Eine 2.te Listenklasse einführen, die von der ersten abgeleitet ist und
die 2.te Verpointerung enthält. Und dann rigoros alle Memberfunktionen
überschreiben, die die jeweilige Funktion aus der Basisklasse aufrufen
und zusätzlich sich noch um die 2.te Verpointerung kümmern.
Karl Heinz Buchegger schrieb:> Eine 2.te Listenklasse einführen, die von der ersten abgeleitet ist und> die 2.te Verpointerung enthält. Und dann rigoros alle Memberfunktionen> überschreiben, die die jeweilige Funktion aus der Basisklasse aufrufen> und zusätzlich sich noch um die 2.te Verpointerung kümmern.
Da die 'speziellen' Treiber aber auch in der 1. Liste weiter verbleiben
sollen müsste er aber auch alle überschriebenen Funkionen der
Parentklasse in seinen neuen Funktionen aufrufen.
Udo Schmitt schrieb:> Da die 'speziellen' Treiber aber auch in der 1. Liste weiter verbleiben> sollen
Ach, ja richtig. Daran hab ich nicht mehr gedacht.
Er hat ja im Grunde eine heterogene Liste. Bei meinen Überlegungen hat
sich jetzt im Kopf die Aufgabenstellung gedreht :-)