Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème de hirarchie de classes

Avec un peu de technique en prime : SDL/OpenGL

    15 août 2007 à 21:18:54

    Bonjour à tous.

    GuilOooo et moi même sommes actuellement en train de réaliser une surcouche orientée objet de la SDL, et pour des raisons de performances, nous utilisons OpenGL pour le dessin de la fenêtre (en 2D uniquement).

    Et nous avons un petit souci au niveau des surfaces.
    Nous n'allons évidement pas passer par la SDL pour cela, puisqu'on fait la vidéo avec OpenGL.
    Donc plus de SDL_Surface, mais on a du mal à se décider sur ce qui doit les remplacer.

    Tout d'abord, on a du mal à décider l'organisation des classes en rapport avec les surfaces. (c'est moins évident qu'il n'y parait ^^).
    Nous sommes d'accord sur le fait qu'il faille séparer les classes de surfaces modifiables des classes de surfaces non-modifiables, ensuite plusieurs options sont possibles :


    première méthode



    Créer une classe de base pour les surfaces non modifiables, qui comprendrait uniquement les méthodes pour créer une surface de couleur unie ou charger une image à partir d'un fichier, et aussi une méthode pour afficher cette surface.
    Puis, créer une classe qui en dérive, prenant une instance de la classe de base en paramètre à la création et permettant de modifier la surface de celle ci.

    L'intérêt est de ne pas pouvoir créer de surface modifiable sans passer par une non modifiable, ce qui ne devrait pas trop surchargé la notation tout en restant simple et clair.

    Image utilisateur
    Les ancêtres sont à gauche et les fils à droite


    Deuxième méthode



    L'autre méthode, serait de créer une classe qui encapsule une surface, modifiable ou non. Une classe abstraite, donc.
    Après quoi, nous pourront alors créer deux sous-classes, héritant chacune de cette classe de base.

    La première sous-classe implémente une surface non-modifiable. La seconde implémente une surface modifiable.
    Bien sûr, une méthode quelconque sera implémentée de manière à pouvoir copier une surface non-modifiable dans une modifiable.

    Le premier intérêt, c'est que l'on peut créer de nouveaux types de surfaces sans forcément passer par l'un des deux existants : ça nous laisse de la marge de manœuvre.
    Le second intérêt, c'est qu'on peut choisir des méthodes pour le rendu totalement différentes pour l'une et pour l'autre des surfaces, tenant compte de leurs caractéristiques respectives, sans devoir "écraser" ce qui est défini dans l'ancêtre (c'est plus délicat quand on code).
    Enfin, il paraît au défenseur de cette méthode plus logique d'utiliser une telle organisation : SurfaceModifiable et SurfaceConstante sont deux spécialisations distinctes d'une Surface, qui est générique, paraît plus clair que SurfaceModifiable est une spécialisation de SurfaceConstante. Dans l'autre sens (SurfaceConstante est une spécialisation de SurfaceModifiable), ça passe encore, mais ici non.

    Image utilisateur
    Les ancêtres sont à gauche et les fils à droite



    Au delà de l'organisation des classes, il y a aussi le problème de la nature de la surface : comment l'implémenter ?


    L'un de nous trouve plus judicieux d'utiliser les textures pour stocker les images chargées, et d'utiliser un GL_QUADS au moment du dessin de la surface pour les couleurs unies.

    Le premier intérêt, c'est que c'est plus simple à gérer.
    Si on utilise des buffers, etc, c'est nous qui gérons la mémoire et on s'expose à des seg faults. OK on est pas des porcs, mais quand même.
    Ensuite, les surfaces constantes ne peuvent être modifiées, seulement affichées : donc GL_QUADS ne ferme pas spécialement de possibilités dans CE cas. Il permet de facilement "colorier" les images (entre autres effets d'openGL).
    Enfin, il y a peut être une différence de performances (dans un sens comme dans l'autre), mais compte tenu du fait que le nombre de surface à gérer ne sera jamais très haut (de l'ordre de 0 à 1000, au très grand maximum), ce n'est pas vraiment un problème.


    L'autre pense qu'il serait préférable de tout stocker indifféremment dans des tableaux de pixels, un peu comme le fait déjà la SDL. Au moment du dessin, il n'y a qu'à afficher les pixels, toujours de la même manière.
    Ceci permet de limiter le nombre d'attributs dans les classes concernant les surfaces (pas de différences entre image et couleur unie), et aussi de faciliter le passage à la classe de modification (impossible de modifier un GL_QUADS...)



    Voilà pour la situation. ^^
    Nous aimerions donc avoir votre avis sur ces questions, autant du point de vue de l'utilisateur de notre bibliothèque que du programmeur qui regarde son code source.

    Merci d'avance, et bonne journée :)
    • Partager sur Facebook
    • Partager sur Twitter
      16 août 2007 à 0:13:34

      Personnellement je vous conseille la première méthode.
      En général, l'affichage d'une surface fonctionne de la même manière que l'objet soit modifiable ou non. Et même si la sous-classe peut le faire un peu différemment rien n'empêche d'ajouter des méthodes spécifiques, au contraire c'est l'intérêt de l'héritage.
      De plus la sous-classe n'a pas besoin de définir d'autres variables d'instance, une surface est définie de la même manière qu'elle soit modifiable ou non, mais créer un objet de la sous-classe permet de modifier la surface, alors que créer un objet de la super-classe permet de dire "cette surface ne changera pas".

      En outre,vous pouvez gérer beaucoup plus facilement la transformation d'un type en un autre si l'une des classes hérite de l'autre. Si par exemple vous voulez créer une copie non modifiable à partir d'une surface modifiable c'est largement simplifié. Créer deux classes différentes signifieraient que les deux objets sont complètement différents, comme le serait une string et un tableau... Hors en l'occurrence il s'agit plutôt d'objet strictement identique, la seule différence c'est que dans un cas on en autorise la modification dans l'autre non.
      • Partager sur Facebook
      • Partager sur Twitter
        16 août 2007 à 9:20:24

        Le but de l'héritge est justement de mettre tout ce qui est commun dans la classe mère (ou ancêtre comme tu l'appelles). Le choix le plus judicieux selon moi est le numéro 2.
        Puisqu'il y a très peu de différences entre les 2, cela me parait plus judicieux.

        De plus en utilisant le polymorphisme, vous pourrez créer des collections hétérogènes de surface.

        Je rejouterais un argument en défaveur de la méthode 1): Souvent, la notion d'héritage s'utilise avec la relation EST UN.
        Est-ce qu'une surface modifiable EST UNE surface non-modifiable ? d'après moi non.
        Est-ce qu'une surface modifiable EST UNE surface de base ? plutôt oui

        Si lorsque tu crées l'héritage, tu dois redéfinir tout les fonctions membres, c'est que ta relation d'héritage n'avait pas de sens.
        • Partager sur Facebook
        • Partager sur Twitter
        Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
          16 août 2007 à 10:57:02

          Pourquoi faudrait-il redéfinir toutes les méthodes dans la sous-classe ? Dans le pire des cas tu redéfinis 2, 3 méthodes et c'est tout, la majorité des ajouts de la sous-classe sont des méthodes permettant la modification de la surface...
          L'un des principes de l'héritage c'est de permettre la factorisation du code, d'après moi une surface qu'elle soit modifiable ou pas se construit de la même manière, le principe étant de stocker la taille de la surface et son contenu, ça se construit de la même manière. Donc la classe surface modifiable aura beaucoup de code qui sera exactement le même que la classe non modifiable, mais en revanche, la classe modifiable rajoutera des méthodes permettant la modifications de la surface...
          Parmi les objectifs de l'héritage, il y a aussi le fait que les sous-classes ajoutent à leur super-classe de nouvelles fonctionnalités.

          Pour finir, la super-classe peut très bien se nommée : Surface et la sous-classe SurfaceModifiable, et là la relation EST UN marche très bien : une SurfaceModifiable EST UNE Surface, mais une Surface n'est pas forcément une SurfaceModifiable...
          • Partager sur Facebook
          • Partager sur Twitter
            16 août 2007 à 11:33:41

            Citation

            Pour finir, la super-classe peut très bien se nommée : Surface et la sous-classe SurfaceModifiable, et là la relation EST UN marche très bien : une SurfaceModifiable EST UNE Surface, mais une Surface n'est pas forcément une SurfaceModifiable...



            Sauf qu'ici tu triches un peu. OK la surface de base s'appellera surface, mais ça n'empêche pas qu'elle sera toujours pas modifiable. Il faudrait ici parler des caractéristiques des objets plutôt que de leurs types, en fait.

            Bon c'est bien ce qu'on pensait, c'est deux visions complètement différentes de la chose.

            Sinon, je vous rappelle qu'on va peut être utiliser des GL_QUADS pour les surfaces non-modifiables et des tableaux de pixels dans les surfaces modifiables : bref, que la méthode pour rendre ne sera pas nécéssairement la même (c'est l'objet de la seconde question).
            • Partager sur Facebook
            • Partager sur Twitter
            J'ai déménagé sur Zeste de savoir — Ex-manager des modérateurs.
              16 août 2007 à 11:38:00

              Personellement j'utiliserai des GL_QUADS pour les 2.

              Pourquoi s'embêter à gérer pixel par pixel alors que l'outil existe déjà ?

              Si tu utilises une implémentation différente pour les 2 types de surface, alors il y a selon moi aucun sens de faire de l'héritage, les choses deviennent trop différentes.
              • Partager sur Facebook
              • Partager sur Twitter
              Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
                16 août 2007 à 12:04:01

                Citation : Nanoc

                Personellement j'utiliserai des GL_QUADS pour les 2.

                Pourquoi s'embêter à gérer pixel par pixel alors que l'outil existe déjà ?



                Précisement pour avoir un controle de la surface au pixel près. ^^
                Par exemple pour réaliser une fonction de masquage, c'est impossible à faire si tu ne contrôle pas tout les pixels de la surface.
                C'est vrai que pour la surface non modifiable, cette méthode est plus simple, mais elle n'est pas apliccable aux surfaces modifiables.


                Citation : Nanoc

                Si tu utilises une implémentation différente pour les 2 types de surface, alors il y a selon moi aucun sens de faire de l'héritage, les choses deviennent trop différentes.


                Je n'irait pas jusqu'à dire qu'il n'y a aucun sens mais je trouve aussi que c'est moins logique que la première méthode.
                (m'enfin c'est assez subjectif ça)
                • Partager sur Facebook
                • Partager sur Twitter

                Problème de hirarchie de classes

                × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                • Editeur
                • Markdown