2010-02-06 11 views
0

J'ai une liste des parties et certains d'entre eux ont besoin d'un pointeur vers un moteur, permet de les appeler EngineParts. Ce que je veux, c'est trouver ces EngineParts en utilisant RTTI et ensuite leur donner le moteur.fournissant la dépendance par classe de base

Le problème est de savoir comment concevoir le EnginePart. J'ai deux options ici, décrites ci-dessous, et je ne sais pas lequel choisir. L'option 1 est plus rapide car elle n'a pas de fonction virtuelle. L'option 2 est plus facile si je veux clone() l'objet car sans données, il n'a pas besoin d'une fonction clone().

Des pensées? Peut-être qu'il y a une troisième option?

Option 1:


class Part; 

class EnginePart : public Part { 
    protected: Engine *engine 
    public: void SetEngine(Engine *e) {engine = e} 
}; 

class Clutch : public EnginePart { 
    // code that uses this->engine 
} 

Option 2:


class Part; 

class EnginePart : public Part { 
    public: virtual void SetEngine(Engine *e)=0; 
}; 

class Clutch : public EnginePart { 
    private: Engine *engine; 
    public: void SetEngine(Engine *e) { engine = e; } 
    // code that uses this->engine 
} 

(Notez que la situation réelle est un peu plus impliqué, je ne peux pas utiliser une solution simple comme la création une liste séparée pour EngineParts)

Merci

+0

Peut-être que je devrais dire un peu plus. Il s'agit en fait d'un hybride d'un graphe et d'un arbre n-aire chargé à partir du disque et les pièces sont créées par le chargeur à l'aide d'une fabrique abstraite. Les parties supérieures n ont besoin de propriétés globales (j'ai utilisé Moteur comme propriété d'exemple) qui ne sont pas contenues dans le graphique lui-même. C'est pourquoi je ne peux pas le fournir dans le constructeur, je dois l'injecter par la suite. – Eric

Répondre

0

Dommage que la réponse indiquant que « une partie ne peut pas tenir le moteur » est supprimé parce que c'était en fait la solution.

Depuis pas le moteur complet est nécessaire, j'ai trouvé une troisième voie:


class Part; 

class EngineSettings { 
    private: 
     Engine *engine 
     friend class Engine; 
     void SetEngine(Engine *e) {engine = e} 
    public: 
     Value* GetSomeValue(params) { return engine->GetSomeValue(params); } 
}; 

class Clutch : public Part, public EngineSettings { 
    // code that uses GetSomeValue(params) instead of engine->GetSomeValue(params) 
} 

Parce que GetSomeValue() a besoin de quelques params qui moteur ne peut pas savoir, il n'y a aucun moyen il pourrait « injecter » cette valeur comme le pointeur du moteur a été injecté dans les options 1 et 2. (Bon ... à moins que je ne fournisse aussi un GetParams virtuel()).

Cela cache le moteur de l'embrayage et me donne à peu près une seule façon de le coder.

0

Les fonctions virtuelles dans les compilateurs modernes (d'environ 10 ans) sont très rapides, en particulier pour les cibles de machines de bureau, et que la vitesse ne devrait pas affecter votre conception. Vous avez toujours besoin d'une méthode de clonage, si vous voulez copier à partir d'un pointeur-/reference-to-base, car vous devez autoriser (pour le moment) les classes dérivées à se copier, y compris les détails d'implémentation comme vtable pointeurs. (Bien que si vous vous en teniez à un compilateur/implémentation, vous pouvez prendre des raccourcis basés dessus, et juste les réévaluer chaque fois que vous voulez utiliser un autre compilateur ou mettre à jour votre compilateur.)

les critères que vous avez énumérés, de sorte que vous êtes de retour à ne pas savoir comment choisir. Mais c'est facile: choisissez celui qui vous convient le mieux. (Ce qui c'est, je ne peux pas dire sur la base de cet exemple maquillé, mais je soupçonne que c'est le premier.)