NAS

C++ Objekte unterschiedlicher Art zur Laufzeit kombinieren

Zisko

Lt. Junior Grade
Registriert
Juli 2010
Beiträge
462
Hallo zusammen,

ich stehe vor einem Problem und bin nicht sicher ob es überhaupt so lösbar ist, wie ich es mir vorstelle.

Es existieren zwei Klassen ClassA und ClassB. Sie besitzen unterschiedliche Attribute aber eine gemeinsame Methode, die einen float als Rückgabewert hat.

Ich möchte an eine übergeordneten Klasse einen Parameter übergeben, der A, B oder AB sein kann. Abhängig von diesem Parameter geschieht folgendes:

A:

Es wird ein Objekt von ClassA erzeugt, alle Parameter an A übergeben, der float Wert berechnet und zurückgegeben.

B:

Siehe A, jetzt das gleiche mit B.

AB:

Es werden A und B erzeugt, parametriert und anschließend die Addition beider float Werte zurückgegeben.

Ich dachte erst an ein Strategie-Pattern, da ClassA und ClassB den gleichen Methodennamen haben zur Berechnung des Algorithmus. Aber das Problem ist, dass A und B völlig unterschiedliche Parameter haben.
Darüber hinaus weiß ich erst bei der Übergabe des Parameters A, B oder AB ob ich eine oder zwei Klassen instanziiere.

Vielleicht könnt ihr mir da weiterhelfen. Bei bedarf kann ich auch etwas Beispielcode zusammenstellen.
 
Also verstehe ich das richtig:
Code:
ClassA InstanzA = new ClassA(parameter1, parameter2);
ClassB InstanzB = new ClassB(parameter3, parameter4);
if(Bedingung)
{
float f = InstanzA.BerechneterWert + InstanzB.BerechneterWert;
}

Wo ist das Problem?
 
Zuletzt bearbeitet:
Diese einfache Art der Implementierung führt dazu, dass ich für jede Kombination (A, B, AB) eine if, bzw. switch/case Bedingung vorsehen muss. Das mag bei zwei Klassen noch überschaubar sein, wird bei 20 Klassen und ihren Kombinationen jedoch sehr unelegant, und verbraucht durch die Aufwendige switch/case Abgefrage bei jedem Aufruf unnötige Ressourcen. Dazu kommt, dass ich für jede Klasse ein Objekt anlegen müsste, auch wenn ich es garnicht benötige.

Mir kam erst das Strategy-Pattern in den Sinn, bei dem ClassA, ClassB, ... ClassX von einem Interface erbt, dass ich dynamisch zur Laufzeit erzeuge. Das Problem ist jedoch, dass es bei Kombinationen aus verschiedenen Klassen nicht umsetzbar ist und die Übergabe von verschiedenen Parametersätzen nicht möglich ist.
 
Es existieren zwei Klassen ClassA und ClassB. Sie besitzen unterschiedliche Attribute aber eine gemeinsame Methode, die einen float als Rückgabewert hat.
Wie können denn zwei Klassen die nicht über irgendeine Vererbung in Beziehung stehen eine gemeinsame Methode haben?
 
Zisko schrieb:
Dazu kommt, dass ich für jede Klasse ein Objekt anlegen müsste, auch wenn ich es garnicht benötige.
was hindert dich daran, die objekte erst dann zu erzeugen, wenn du sie brauchst?

so ein paar verschachtelte if-abfragen sind außerdem eigentlich nicht sonderlich ressourcenfressend, schließlich brauchst du ja nur eine tiefe von log(n), um n klassen auseinanderzuhalten.

wenn dir das zu langsam ist, kannst du natürlich einen array, der durch die parameter "A", "B", "AB" etc indiziert wird, anlegen, in dem sich dann objekte oder funktionspointer befinden, die dann die objekte der klassen A, B, usw erzeugen und auswerten.

edit: falls du statt ifs ein switch-statement verwendest und den parameter so kodierst, dass nur kleine zahlen entstehen, möglichst ohne lücken, kann der compiler diese optimierung natürlich auch vornehmen, sodass du in O(1) zum richtigen fall springst.
 
Zuletzt bearbeitet:
kuddlmuddl schrieb:
Wie können denn zwei Klassen die nicht über irgendeine Vererbung in Beziehung stehen eine gemeinsame Methode haben?

Ganz einfach:

Code:
class A {
    int bar;
    int foo(int i);
}

class B {
    int quux;
    int foo(int i);
}

@TE: Eine Möglichkeit wäre, beide Klassen von einer abstrakten Oberklasse erben zu lassen (da C++ Mehrfachvererbung unterstützt, geht das auch, falls die Klassen schon in einer bestehenden Vererbungshierarchie drinstecken) und die gemeinsame Methode in dieser Oberklasse zu deklarieren.
 
Also wenn du 20 solche Klassen hast, dann ist die Abfrage dein geringstes Problem.

Eine Schleife von 1 bis 20, und immer ein Test "Wenn KlasseX == Laufvariable dann erstelle die Klasse über ein Template, lass die float zurück geben und addiere sie auf eine Gesamtvariable, am Ende gib die Gesamtvariable zurück."
Angenommen die Klassenkombination steckt im Array welcheklasse[]
Code:
float Rueckgabe = 0.0;
	for (int i=0; i<=19; ++i)
	{
		if( find(welcheklasse.begin(), welcheklasse.end(), i) != welcheklasse.end() )
		{
			Rueckgabe += KlasseX_erzeugen_und_float_zurueckgeben(i);
		}
	}

Was mich beschäftigen würde, wäre, die Anzahl der Klassen zu reduzieren, über Templates, Vererbung und übergebene Parameter.
 
Zuletzt bearbeitet:
mir klingt es tatsächlich danach das du hier wohl von abstrakten Basisklassen gebrauch machen solltest. Das Problem wird später jedoch die Co- und Kontravarianz deiner Klassen zueinander, sobald sich ihre restlichen Objekteigenschaften unterscheiden.

Eine einfache Lösung wäre, dass du eine clone funktion zur tiefen Kopie anlegst (oder auf jeden dir lieben weg) um eine temporäre Kopie für einen Typecast anlegst. Dieser Typcast wird dir alle restinformationen zum des Objekts "weg schneiden". Natürlich muss der nötige Floatwert zur Rückgabe auch in der Abstrakten Basisklassen verfügbar sein. So bekommst du für deine Methode ein einheitliches Objekt zur Berechnung deiner Daten.

Schlauer wäre es jedoch hier, eine Addmethode schon im eigentlichen Basisobjekt mit einem anderen Basisobjekt zu hinterlegen und diese dann rekursiv aufzurufen und am Ende ein "Ergebnisobjekt" zu erhalten. Da jede weitere Klasse vom selben Interfacetyp ist, ist diese auch typenverträglich und kann deine Basisdaten benutzen.

Ein weiterer, aber weit komplizierterer Weg wäre eine Implementierung von einer Kovarianten Klassenstruktur samt Basisklassen und Interfaces um dir ohne Typecast/Informationsverlust bzw ohne den größeren Speicherbedarf eine ordentliche addition mehrerer unterschiedlicher Objekte gelingt. Das hat den Vorteil das du dieses Stück Software für die Ewigkeit schreibst. Sauber geplant und mathematisch korrekt implementiert ist das natürlich eine kleine Wunderwaffe.

Falls weiter fragen bestehen, schreib mich einfach an :)

Gruß!
 
Zurück
Oben