Forum: Mikrocontroller und Digitale Elektronik C++: Wie nutzen 2 vererbte Objekte selben Speicherbereich?


von Alexander I. (daedalus)


Lesenswert?

Hallo,

ich möchte folgendes machen:
1
class father
2
{
3
 protected:
4
  unsigned char data[4]; //Testdaten: a b c d
5
}
6
7
class son : public father
8
{
9
 private:
10
  unsigned char data0; // Testdaten: x
11
  unsigned char data1; // Testdaten: y
12
  unsigned int data23; // Testdaten: 150
13
}
14
15
son Myson = new son();

Im Speicher wird für Myson dann folgendes abgebildet
... #1 #2 #3 #4 #5 #6 #7 #8 ...    // Speicheradresse
...  a  b  c  d  x  y  0  150 ...  // Daten

Jetzt ist meine Idee folgende:
Ein anderes Objekt "other" erwartet als Übergabe-Parameter "father" und 
verarbeitet die Daten in "data". Wenn ich jetzt "other" den "Myson" 
übergebe, akzeptiert der Compiler das ja ohne weiteres, meine Intention 
ist aber: data0,data1,data23 ist equivalent zu data[0], data[1], data[2] 
und data[3], es soll also tatsächlich derselbe Speicherbereich genutzt 
werden, da "other" völlig egal ist, was in "data" steht, es für mich 
aber leichter ist, die Menge an Bytes in bstimmte Variablen zu 
unterteilen. Das müsste dann also so aussehen, dass data[] auf data0 
zeigt, im Speicher würde dann nur noch stehen:

... #1 #2 #3 #4 #5 #6 #7 #8 ... // Speicheradresse
...  x  y  0  150 ...           // Daten

Ich hoffe es ist klar, was ich da möchte? Gibts da einen Königsweg einen 
bereits definierten Datenbereich zu "spezialisieren"?

Vielen Dank schonmal im Vorraus

von Karl H. (kbuchegg)


Lesenswert?

Alex Wurst wrote:

Die vernünftigste Lösung für dein Problem ist es, wenn
du deiner son Klasse ein paar Zugriffsunktionen verpasst
über die son auf das Array zugreifen kann. Da das Array
protected ist, ist das auch legal.

Alles andere ist Murks.
1
class father
2
{
3
 protected:
4
  unsigned char data[4]; //Testdaten: a b c d
5
};
6
7
class son : public father
8
{
9
  public:
10
      
11
  unsigned char& data0()   { return data[0]; }
12
  unsigned char& data1()   { return data[1]; }
13
  int&           data23()  { return *(int*)&data[2]; }
14
};
15
16
int main()
17
{
18
  son a;
19
20
  a.data23() = 5;
21
}

von OliverSo (Gast)


Lesenswert?

Ein alternativer Murks wäre eine entsprechende union in class father.

Oliver

von Karl H. (kbuchegg)


Lesenswert?

OliverSo wrote:
> Ein alternativer Murks wäre eine entsprechende union in class father.

Ich denke die Absicht hinter der Ableitung besteht darin dass
es irgendwann mal mehrer abgeleitete Klassen geben wird, die
den Byte Buffer verschieden interpretieren. Sowas kann man
zb. machen, wenn über eine Schnittstelle eine Message hereinkommt,
es verschiedene Message Typen gibt und sich der bytemässige Aufbau
je nach MessageTyp unterscheidet.

Mit einer union trägt man dann das Wissen über den unterschiedlichen
Aufbau aller Messages in die Basisklasse wo man es aber eigentlich
nicht haben möchte.

von Alexander I. (daedalus)


Lesenswert?

Richtig erkannt, Karl-Heinz,
es handelt sich hier um eine Art Netzwerkprotokoll nach ISO/OSI-Modell 
und da ist sowas durchaus sinnvoll, denn ein PHY-Layer braucht nicht die 
Infos des MAC-Layers verarbeiten sondern diese nur als Payload 
weiterreichen. Lösung?

von Alexander I. (daedalus)


Lesenswert?

Ah, habe den ersten Post übersehen. Ich schaus mir mal an, vielen Dank.

von OliverSo (Gast)


Lesenswert?

>es soll also tatsächlich derselbe Speicherbereich genutzt
>werden

Die Lösung per getter ist natürlich mit Abstand die sauberste, um die 
unterschiedlichen views auf die Daten zu erzeugen.

Allerdings nutzt das Beispiel oben nicht den SELBEN Speicherbereich - 
ein per new() oder statisch neu angelegter son hat einen eigenen 
Speicherbereich für die gererbte data-Struktur, und die müsste im 
Konstruktor, wie auch immer, noch gefüllt werden. (Dann könnte man die 
Daten auch gleich dort übersetzten).

Auf Zugriff auf den SELBEN Speicherbereich geht wohl nur per pointer, 
der dann kopiert werden muß. Das spart bei einer 4-byte-Datenstruktur 
aber nicht wirklich viel ein :-)

Oliver

von Ingo E. (ogni42)


Lesenswert?

Die beschriebene Anwendung klingt aber nicht nach Vererbung 
("ist-ein-Beziehung") denn ein PHY-Layer-Objekt ist kein 
MAC-Layer-Objekt. Beide zeigen nur eine Sicht auf bzw. einen Ausschnitt 
eines Datum.

IMHO würde daher besser ein Objekt für das Netzwerkdatum passen. Die 
einzelnen Layer-Objekte haben evtl eine gemeinsame Basisklasse, die 
gemeinsame Informationen bereitstellt (z.B. Layername, ...) und 
Zugriffsmethoden, die die entsprechenden Daten bereitstellen.

von Alexander I. (daedalus)


Lesenswert?

Hallo,

die Layer-Objekte verarbeiten verschiedene Datumsobjekte. Ums mal 
korrekt auszudrücken: MAC-Layer "ist ein" PHY-Layer, greift also auf die 
Funktionen von PHY zu und kapselt diese nach Außen hin. Der PHY-Layer 
soll lediglich mit Datenobjekten vom Typ "Container" arbeiten können, 
also im Endeffekt einen Menge an Bytes die übertragen werden, mit nahezu 
keinen Steuerdaten. Der MAC-Layer dagegen kann auch Datenobjekte vom Typ 
"Frame" verarbeiten und teilt dem PHY-Layer mit Hilfe der Headerdaten 
mit, was dieser zu tun hat (Hardware-Adressierung, Datenrate, etc.), 
übergibt diesem die Daten aber indem er sie zuvor zu einem "Container" 
castet.

Es bleiben ja nach wie vor dieselben Daten, nur einmal als Menge an 
Bytes betrachtet und einmal als Datenpaket mit interpretierbarem 
MAC-Header.

Das PHY/MAC-Gedöhns ist schon implementiert, funktioniert auch und kann 
3 Wochen vor Diplomarbeitsabgabe nicht mehr großartig geändert werden ;)

Es geht mir also nur um die Darstellung von denselben Daten aus 
unterschiedlichen Perspektiven. Es können natürlich zum gleichen 
Zeitpunkt mehrere Container/Mac-Objekte existieren, die aber in 
verschiedenen Speicherbereichen liegen, wobei aber zusammengehörender 
Container und MAC-Frame dieselben Datenbytes enthalten, also auch 
denselben Speicherbereuch nutzen.

Viele Pointer möchte ich nach Möglichkeit verhindern, denn dann habe ich 
ja nahezu keine Speicherersparnis, da die einzelnen Datenelemente nur 
1-4 Byte groß sind.

von OliverSo (Gast)


Lesenswert?

Wenn du tatsächlich die Daten nur einmal im Speicher haben willst, dann 
solltest du auch beachten, wie dein Compiler Daten im Speicher anordnet. 
Ein Compiler legt, abhängig von der Zielarchitektur, sowas wie
1
char data0; char data1; int data23;
 nicht in aufeinanderfolgende Bytes, sondern z.B. jede Variable auf eine 
gerade Adresse. Um man das zu verhindern, gibt es entsprechende 
Compilerdirectiven. Näheres sollte die Compiler-Doku enthalten.

Oliver

von 6636 (Gast)


Lesenswert?

Alex,
wenn du den Speicher ein paar Pointer nicht hast, so ist C++ 
moeglicherweise uebertrieben. Wie hat man's frueher gemacht : Globaler 
Speicher, ein Array, und man uebergibt einen Index. Der Rest sind 
Schulbeispiele.

von Unbekannter (Gast)


Lesenswert?

Das ist doch hier alles Murks.

> Es bleiben ja nach wie vor dieselben Daten, nur einmal als Menge an
> Bytes betrachtet und einmal als Datenpaket mit interpretierbarem
> MAC-Header.

Das ist der entscheidende Punkt:

  Verschiede Sichten auf ein und den selben Datenblock!


> Das PHY/MAC-Gedöhns ist schon implementiert, funktioniert auch und
> kann 3 Wochen vor Diplomarbeitsabgabe nicht mehr großartig geändert
> werden

Gut, dann gibt den Schrott eben ab. Aber nicht über die schlechte 
Bewertung jammern.

von Alexander I. (daedalus)


Lesenswert?

So, ich habe die Sache jetzt gelöst wie Karl-Heinz es vorgeschlagen hat, 
funktioniert prima und verbraucht nur unwesentlich mehr ROM als meine 
vorherige Lösung.

@Unbekannter:
Ganz großes Kino! Mach es doch einfach besser und bring einen 
konstruktiven Vorschlag. Wer soll mit so einem sinnlosen Kommentar denn 
was anfangen?

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
Noch kein Account? Hier anmelden.