Je crée quelques classes Vector2
(X & Y) et Vector3
(X, Y & Z), mais je ne sais pas si je dois Vector3
hériter de Vector2
, ou si je dois réimplémenter les variables membres m_x
et m_y
encore? Quels sont les avantages et les inconvénients de chaque côté (héritage vs redéfinition).
Edit: j'utilise C ++ (VS2010).
c++
architecture
Mark Ingram
la source
la source
Vector3
devrait être seulement 3floats
en ce qui concerne la mémoire. Je ne dis pas que c'est impossible, juste que je n'ai jamais vu ça dans un moteur de production.floats
. Vous savez, YAGNI, KISS, tout ça.Vector2
,Vector3
etVector4
sans héritage etfloats
seulement est vraiment la norme de facto dans les moteurs de jeu.typedef float real;
;).Réponses:
Non, ça ne devrait pas. La seule chose que vous utiliseriez de l'héritage est les composants
x
ety
. Les méthodes utilisées dans uneVector2
classe ne seraient pas utiles dans uneVector3
classe, elles prendraient probablement différents arguments et effectueraient des opérations sur un nombre différent de variables membres.la source
Vector3
IS-NOT-AVector2
(donc il ne doit pas hériter), mais unApple
IS-AFruit
(donc il peut hériter). Si vous tordez assez votre esprit, unVector3
HAS-AVector2
dedans, mais la perte de performance et le codage difficile signifient que vous écrirez des classes complètement séparées pourVector3
etVector2
.Il y a une chose curieuse que vous pouvez faire avec C ++ (Vous n'avez pas spécifié de langage, et cette réponse est principalement parce que je pense que c'est agréable de voir des alternatives, bien que je ne pense pas vraiment que cela soit utile dans la plupart des cas.)
En utilisant des modèles, vous pouvez faire quelque chose comme ceci:
et cela peut être utilisé comme ceci:
Comme je l'ai dit, je ne pense pas que ce soit utile, et cela compliquera probablement votre vie lorsque vous essayez d'implémenter dot / normaliser / autre et d'essayer d'être générique avec un certain nombre de vecteurs.
la source
Vector3f v
un peu plus gonfléVector3<float> v
typedef
.Quelle que soit la vitesse, la première question que vous devez vous poser lorsque vous effectuez un héritage est de savoir si vous allez les utiliser de manière polymorphe. Plus précisément, existe-t-il une situation où vous pouvez vous voir utiliser un
Vector3
comme si c'était unVector2
(qui, en héritant de celui-ci, vous dites explicitement qu'un Vector3 "est-un" Vector2).Sinon, vous ne devez pas utiliser l'héritage. Vous ne devez pas utiliser l'héritage pour partager du code. C'est à cela que servent les composants et les fonctions externes, pas que vous partagiez de tout code entre eux de toute façon.
Cela étant dit, vous voudrez peut-être des moyens simples de convertir
Vector3
s enVector2
s, et dans ce cas, vous pouvez écrire une surcharge d'opérateur qui tronquera implicitement leVector3
en aVector2
. Mais vous ne devriez pas hériter.la source
Vector2
mais d'hériter d'une baseVector<N>
? Cela est parfaitement logique. De plus, pourquoi l'héritage signifie-t-il automatiquement un comportement polymorphe? L'une des meilleures choses à propos de C ++ est que vous pouvez avoir un héritage à coût nul. Pas besoin d'ajouter de méthodes virtuelles (y compris des destructeurs virtuels) dans laVector<N>
classe de base .Non, car chaque méthode devra également être remplacée, vous n'aurez donc pas besoin d'en hériter.
Si quelque chose, ils pourraient tous deux implémenter une interface vectorielle. Cependant, comme vous ne voulez probablement pas ajouter / sub / dot / dst entre un Vector2 et un Vector3, cela aura des effets secondaires indésirables. Et avoir différents paramètres, etc. serait un problème.
Donc, je ne vois vraiment aucun avantage de l'héritage / interface dans ce cas.
Un exemple est le framework Libgdx, où Vector2 et Vector3 n'ont rien à voir l'un avec l'autre, à part avoir le même type de méthodes.
la source
Si vous prévoyez d'utiliser des baies SIMD sont probablement les meilleures. Si vous souhaitez toujours utiliser la surcharge d'opérateur, vous pouvez envisager d'utiliser une interface / mixin pour accéder au tableau sous-jacent - par exemple, voici un point de départ qui n'a que le (non testé)
Add
.Remarquez comment je n'ai pas fourni
X
/Y
/Z
, chaqueVectorX
classe hériterait directement de celle-ci - pour les mêmes raisons spécifiées par d'autres personnes. Pourtant, j'ai vu des tableaux utilisés comme vecteurs à plusieurs reprises dans la nature.Avertissement: Mon C ++ pourrait être nul, cela fait un moment que je ne l'ai pas utilisé.
la source
_aligned_malloc
signifie que le bogue que j'ai ouvert n'est pas vraiment un bogue?__m128
registre, vous devez_mm_loadu_ps
plutôt utiliser Un bon exemple de classe est ici sous "vectorclass.zip"_mm_loadu_ps
devrait fonctionner pour vous avec cette structure (où_mm_load_ps
pas). J'ai également ajouté votre suggestion - n'hésitez pas à modifier la question si vous pensez que j'aboie le mauvais arbre (cela fait un moment que je n'ai pas utilisé C [++]).Un autre inconvénient sérieux pour que Vec3 hérite de Vec2 ou, sans doute, pour que les deux héritent d'une seule classe Vector: votre code fera beaucoupd'opérations sur des vecteurs, souvent dans des situations critiques, et il est dans votre intérêt de vous assurer que toutes ces opérations sont aussi rapides qu'elles le peuvent - beaucoup plus que pour de nombreux autres objets qui ne le sont pas tout à fait si universel ou bas niveau. Alors qu'un bon compilateur fera de son mieux pour aplanir les frais généraux d'héritage, vous comptez toujours plus sur le compilateur que vous ne le souhaiteriez; au lieu de cela, je les construirais comme des structures avec le moins de frais généraux possible et j'essaierais peut-être même de faire en sorte que la plupart des fonctions qui les utilisent (à l'exception de choses comme operator + qui ne peuvent pas vraiment être aidées) soient globales plutôt que des méthodes sur le struct. Une optimisation précoce est généralement recommandée contre, et pour une bonne raison,
la source