C++ Vererbung mehrere Klassen und ein Array

F

Furtano

Gast
Vererbung mehrere Klassen und ein Vector

Hallo,

ich möchte die Super-Klasse Breed haben, von der einige Klassen wie z.B. Egg abgeleitet werden.

jetzt packe ich ein / mehrere Objekte der abgeleiteten Klasse in ein Breed Vector.

PHP:
std::vector  <Breed> breed;

....

if (days % 3){
	Egg egg;
	egg.days = 0;
	egg.lifeStatus = true;
	breed.push_back(egg);
}

Leider geht der Zugriff hier nicht, weil statusOfAnt angeblich kein Member von Breed ist.
Wie behebe ich das?
Ich möchte nicht für jede Abgeleitete Klasse einen eigenen Vector sondern alle abgeleiteten Klassen-Objekte ins Breed Array schieben und auswerten.
siehe hier:
PHP:
for (Breed ant : breed){
	if(ant.statusOfAnt == status_EGG)
}




Globals.h
PHP:
enum statusOfAnt {status_EGG,status_GRUB, status_PUPPET, status_IMAGO, status_ANT};

Breed.h
PHP:
#ifndef BREED
#define BREED
#include "Globals.h"

class Breed {

	public:		
		statusOfAnt status;
		int days;
		int endDate;
		int food;
		// 0 == Dead, 1 == Alive 
		bool lifeStatus;


};

#endif

Egg.h
PHP:
#ifndef EGG
#define EGG

#include "Breed.h"

class Egg : public Breed {

public:

	Egg (){
		status = status_EGG;
		days = 0;
		endDate = 14;
		food = 10;
		lifeStatus = 0;
	}
	//this.status = status_PUPPET;

};

#endif

Danke ! :)
 
Zuletzt bearbeitet von einem Moderator:
Normalerweise werden Variablen nicht vererbt, wie es allerdings speziell in C++ ist, weiß ich leider nicht.
 
Ok ich trottel, habs schon gefunden hab auf das falsche Attribut zugegriffen, sonst is ja alles richtig :freaky:
Manchmal muss man Rubber Duck Debugging machen ;)
 
xDarkice schrieb:
Normalerweise werden Variablen nicht vererbt, wie es allerdings speziell in C++ ist, weiß ich leider nicht.
Hi,
@xDarkice: Wieso werden Variablen/Felder nicht vererbt? Natürlich werden sie vererbt, sofern diese nicht als private deklariert sind. Das ist nicht nur in C++, sondern in allen OOPs so! ;-)

@Furtano: Bringe den std::vector in deiner Basisklasse "Breed" mit dem Zugriffsmodifizierer "protected" unter. Dann haben alle ableitenden Klassen Zugriff darauf. Btw. deine Destruktoren solltest du als "virtual" deklarieren.

Greetz
hroessler
 
xDarkice schrieb:
Normalerweise werden Variablen nicht vererbt, wie es allerdings speziell in C++ ist, weiß ich leider nicht.

Sorry, aber wieso hältst du es für notwendig, hier deinen Senf dazuzugeben, wenn du offensichtlich nicht den leisesten Hauch einer Ahnung von der Materie hast?


@OP: Keine gute Idee. Polymorphismus bedeutet unterschiedliche Implementierungen der selben Schnittstelle - in C++ vorzugsweise über virtuelle Methoden. Einfach mal direkt in die Innereien (also die Datenmember) deiner abgeleiteten Klasse (und dann auch noch über ein Objekt der Basisklasse, das die Member, die erst in der abgeleiteten Klasse eingeführt werden, NATÜRLICH nicht besitzt) hat nichts mit dem Gedanken von Polymorphismus zu tun.

So jetzt ins Detail:

Code:
std::vector  <Breed> breed;

Vergiß es! Du kannst nicht Objekte einer abgeleiteten Klasse in einem vector von Basisklassen-Objekten speichern. Was du stattdessen tun kannst, ist einen vector von POINTERN auf Basisklassenobjekte anlegen und dann die Adressen von Objekten der abgeleiteten Klasse in diesen vector stecken. Dann kannst du über diese Pointer auf virtuelle Methoden zugreifen. Bitte führ dir das ganze noch mal gründlich in einem Buch / Online-Tutorial zu Gemüte. Das was du da tust, ist einfach nur unheimlich wirr.


P.S. Und natürlich ist statusOfAnt kein Member das Klasse. Das Datenmember heißt bei dir status!
 
@hroessler was bringt das für einen Vorteil?
@antred (ant hihih:)) doch es funktioniert anscheinend (was ich bis jetzt getestet habe), Methoden habe ich jetzt noch nicht eingebaut mir reichen erst mal Attribute
 
Zuletzt bearbeitet von einem Moderator:
hroessler schrieb:
@Furtano: Bringe den std::vector in deiner Basisklasse "Breed" mit dem Zugriffsmodifizierer "protected" unter. Dann haben alle ableitenden Klassen Zugriff darauf.

:confused_alt: :confused_alt:
Der vector ist in seinem Beispiel überhaupt keiner Member irgend einer Klasse (und das hat auch nix mit der Sache zu tun).
 
Furtano schrieb:
@antred (ant hihih:)) doch es funktioniert anscheinend

Das Schlüsselwort ist hier anscheinend. Wenn du einem Objekt der Basisklasse ein Objekt einer abgeleiteten Klasse zuweist, dann passiert etwas häßliches, das sich splicing nennt. Google das einfach mal ... gibt bestimmt einen schönen Wiki-Eintrag dazu.
 
Ok habs Verstanden, wie mache ich das mit den Pointern. Ich hasse Pointer, ich hasse sie so sehr...
In Java dürfte das Slicing kein Problem sein, oder?
 
Splicing, nicht slicing. ;) Ich kann kein Java, aber vermutlich nicht, da in Java meines Wissen eh alle Methoden virtuell sind (und damit wahrscheinlich auch der Zuweisungsoperator).

Zu den Pointern.
Code:
#include <memory> // for std::shared_ptr

// ....
typedef std::shared_ptr< Breed > BreedPtr; // typedef ... damit wir später weniger tippen müssen
std::vector< BreedPtr > vectorOfBreeds;

vectorOfBreeds.push_back( BreedPtr( new Egg ) );

Ich habe hier shared_ptr ( http://en.cppreference.com/w/cpp/memory/shared_ptr ) verwendet, damit du Speicherlecks vermeiden kannst. Wenn du das nicht möchtest, kannst du auch "nackte" Pointer verwenden. Dann liegt die Verantwortung für das Löschen der Breed / Egg Objekte allerdings bei dir, während shared_ptr dafür automatisch sorgt, sobald der vector selbst zerstört wird.

Code:
std::vector< Breed* > vectorOfBreeds;

vectorOfBreeds.push_back( new Egg );
 
Zuletzt bearbeitet:
Super Dankeschön :)
Ergänzung ()

Wie baue ich den Pointer dann hier ein?

PHP:
for (Breed ant : breed){
		if(ant.status == status_EGG){
			std::cout << "\nEgg";
		}
	}

PHP:
if (days % 3 == 0){
	Egg egg;
	egg.days = 0;
	egg.lifeStatus = true;
	breed.push_back(egg);
	std::cout << "EGGTIME\n";
				}
 
Zuletzt bearbeitet von einem Moderator:
Na ja, in deinem for-Schleifen-Kopf heißt es dann eben nicht mehr "Breed ant" sondern "Breed* ant", und statt über den . greifst du halt über -> auf die Member zu.

Verlier aber nicht aus den Augen, dass der direkte Zugriff auf Datenmember nach wie vor am Sinn von Polymorphie (und von OOP im Allgemeinen) vorbeigeht.
Ergänzung ()

Deine Vererbung verstehe ich sowie so nicht so richtig. Breed heißt ja so viel wie Art, Rasse. Warum leitest du Egg von Breed ab? Ableitung impliziert eine is-a relationship (http://en.wikipedia.org/wiki/Is-a). Frag dich mal "Ist ein Ei eine Art/Rasse?"

Doch wohl eher nicht, oder?
 
Huu, deinen Tipp probier ich gleich aus.

Ich mache eine Ameisensimulation.

Breed soll der "Prototyp" für die Zustände und abgeleiteten Klassen Ei -> Larve -> Puppe -> Imago -> Ant

sein. :) Eben den Zustandsübergang den ein Ameisenei bis hin zur fertigen Ant macht :)
 
Das ganze per Vererbung abzubilden macht trotzdem keinen Sinn. Wie antred schon gesagt hat, Vererbung macht sinn wenn man zwischen die beiden Klassen ein "is-a" bzw. "ist ein" packen kann. Also z.B. "Ein Auto ist ein Fahrzeug", ein "Angestellter ist einePerson" etc.

Jetzt frag dich dasselbe mal bei dir: "Eine Larve ist eine Puppe" ist ja ganz offensichtlich falsch. Von demher ist Vererbung hier falsch am Platz.
Wenn dann kannst du eine allgemeine Klasse "AntState" machen und dann Ei, Larve, Puppe, Imago, Ant von AntState ableiten (Hier ist das ist ein ja richtig: Eine Puppe ist ein bestimmter AntState, ein Ei ist ein anderer AntState).
 
antred schrieb:
Splicing, nicht slicing. ;)

Sorry, jetzt muß ich mich doch glatt selbst zitieren, um den Unsinn zu berichtigen, den ich da gepostet habe. :freak: Natürlich heißt es doch slicing (also ohne p). Ich habe keine Ahnung, woher dieser Blödsinn kam ... ich glaube, ich komme langsam in dieses Alter ...
 
@antred hehe, habs trotzdem in google gefunden :)
@stwe so ist es doch schon abgebildet (AntState == Breed):)
 
Zurück
Oben