C
Ich habs jetz so gemacht, das alle meine Elemente ihren Typ kennen. Typ und Name kann man nicht verändern. Über den Namen kann der User seine Elemente später identifizieren. Ist wie in JavaScript mit document.getElementById( "..." )
Anstelle von String könnte ich auch Zahlen oder anderes nehmen, klar. Aber Strings fand ich am besten.
enum ELEMENT_TYPE
{
ET_A = 0,
ET_B,
ET_C
};
template< typename DataType >
class BasicElement
{
private:
ELEMENT_TYPE type;
std::string name;
public:
BasicElement( std::string newName )
: type( ET_A ) name( newName )
{ }
ELEMENT_TYPE getType( )
{
return this->type;
}
std::string getName( )
{
return this->name;
}
};
Dadurch, dass ich den Typ im Element speichere, kann der User nicht nach einem B-Element mit den Namen "foo" suchen, wenn im Vector das Element "foo" vom Typ C ist. Somit wende ich auch keinen falschen dynamic_cast an, á la:
BasicElement* b = new ElementA( ... );
ElementC *c = dynamic_cast<ElementC>( b );
Also gestaltet sich der Manager in etwa so:
template< typename DataType >
class Manager
{
protected:
typedef BasicElement<DataType>* basicType;
std::vector< basicType > elements;
size_t numberOfElements;
template< typename ElemType >
bool addElement( ElemType *newElem )
{
for( size_t i = 0; i < this->numberOfElements; ++i )
{
if( this->elements[i] == NULL ) continue;
if( this->elements[i]->getName() == newElem->getName() )
return false; //Ein Element mit diesem Namen kommt schon vor.
}
this->elemens.push_back( newElem );
++this->numberOfElements;
}
template< typename ElemType >
ElemType* getElement( ELEMENT_TYP type, std::string name )
{
for( size_t i = 0; i < this->numberOfElements; ++i )
{
if( this->elements[i] == NULL ) continue;
if( this->elements[i]->getType() == type &&
this->elements[i]->getName == name
return dynamic_cast<ElemType*>( this->elements[i] );
}
return NULL;
}
public:
Manager( )
: numberOfElements( 0 )
{ }
size_t size( )
{
return this->numberOfElements;
}
size_t deleteElement( std::string name )
{
for( size_t i = 0; i < this->numberOfElements; ++i )
{
if( this->elements[i] == NULL ) continue;
if( this->elements[i]->getName == name )
{
this->elements.erase( this->elements.begin() + i );
--this->numberOfElements;
return true;
}
}
return false;
}
bool addElementA( /* A-spezifische Parameter */ )
{
ElementA *newElem = new ElementA( ... );
return this->addElement<ElementA>( newElem );
}
ElementA* getElementA( std::string name )
{
return this->getElement( ET_A, name );
}
};
So hab ich eigentlich das erreicht, was ich wollte.
Was sagt ihr dazu? verwendbar oder eher grausam?
Zu der Perfomanz würde ich mir eher überlegen ob das Suchen der Objekte via String nicht verbessert werden kann. Möglicherweise wäre ein assoziativer Container sinnvoll. Das musst du aber selber entscheiden was du häufiger brauchst - Suchen vs wahlfreier Zugriff vs Einfügen/Löschen.
Das Programm verläuft eigentlich so, dass der User seine Elemente anfangs anlegt. später will man diese eigentlich nur manipulieren(auslesen,ändern,whatever).
Also Anfangs schnelles Einfügen
In der Mitte schneller Random Access Zugriff
Und am Ende des Programmes schnelle Zerstörung
MfG. Ich