IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

class Vertex: array member ou héritage de valarray ?


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Par défaut class Vertex: array member ou héritage de valarray ?
    Salut les C++,

    Après avoir terminer mon dernier projet: la version 2 de it-edit (Integrated Terminals Editor) que je vous invite a tester si vous êtes sous Linux.

    ---

    J'ai et suis en train, je continue, d'écrire une petite library personnelle pour OpenGL.

    Et donc mon ancienne implémentation de la classe Vertex ressemble a cela:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
     
    #ifndef GL_UTILS_VERTEX_H
    #define GL_UTILS_VERTEX_H
     
     
    #include <array>
    #include <iostream>
    #include <ostream>
     
    using namespace std ;
     
    template <typename T>
    class Vertex {
     
      std::array<T, 4> vertex ;
     
      public :
     
        Vertex() { vertex = {T(0), T(0), T(0), T(0)} ; } ;
     
        Vertex(const Vertex<T> &val) { vertex = val.vertex ; } ;
     
     
     
        Vertex(const T x, const T y, const T z, const T w=1) { vertex={x,y,z,w} ;} ;
     
        Vertex<T>& operator = (const Vertex<T> &val) { vertex = val.vertex ; return *this ; } ;
     
        T& operator [] ( const int idx) { return vertex.at(idx) ; } ;
     
        Vertex& operator -() {
     
          vertex[0] = -vertex[0] ;
          vertex[1] = -vertex[1] ;
          vertex[2] = -vertex[2] ;
     
          return *this ;
        }
     
        // ...
    } ;
     
    #endif
    Et la nouvelle implémentation de la classe Vertex ressemble a ceçi:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
     
    #ifndef GL_UTILS_VERTEX_H
    #define GL_UTILS_VERTEX_H
     
     
    #include "./../../headers/includes.h"
    // #include "./../../headers/defines.h" #define GL_UTILS_TYPE float // defined in this file.
     
    #include <valarray>
     
    using namespace std ;
     
    class Vertex : valarray<GL_UTILS_TYPE> {
     
      public :
     
        //GL_UTILS_TYPE x = valarray[0] ; this doesn't work i don't know how to implement it.
     
        Vertex() : valarray(3) {} ;
     
        Vertex(const GL_UTILS_TYPE x, const GL_UTILS_TYPE y, const GL_UTILS_TYPE z) : valarray{x,y,z} {} ;
     
        friend ostream& operator<<(ostream &os, Vertex &vertex) {
     
          os << "Vertex at x: " << vertex[0] << ", y: " << vertex[1] << ", z: " << vertex[2] << endl ;
     
          return os ;
     
        } ;
     
        // Is this right to get a pointer on the start of valarray ?
        GL_UTILS_TYPE *get_vertex() { return (GL_UTILS_TYPE *) this ; }    
     
       // To be continued...
     
    } ;
     
    #endif
    Quel est la meilleur solution d'implémentation a votre humble avis:

    1. un membre array de la classe Vertex et écrire tous l'overloading d'opérateur ?

    ou

    2. une classe Vertex héritant de la classe valarray, héritant de tous les bienfaits du valarray.

    ---

    Sinon vous aurez sans doute remarquer que la première implémentation de la classe Vertex est une `template class`.

    Le problème est que je n'arrive pas a compiler en fichier objet une classe template, pour des classes ayant plus de méthodes complexes.


    Que j'aimerai séparer du *.h en fichier *.cpp compilable en fichier objet.


    Est-ce parce que un template n'est pas compilable en fichier objet et sinon dans le cas contraire alors comment faire ???

    ---

    Merci pour vos réponses et votre précieuse aide illuminant les ténèbres de mon ignorance.

  2. #2
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Personnellement, je préfère le std::array, parce que sa taille est fixé à la compilation.
    Il n'y a pas d'allocation dynamique, alors qu'il est probable que valarray le fasse, puisse que la taille est un argument de son constructeur.

    Par contre, dans le cas de ta version array, il serait bon que le constructeur soit écrit ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        Vertex(): vertex{0,0,0,0} {}
         Vertex(const Vertex<T> &val) : vertex(val.vertex) {}
    Ainsi, tu n'aurais pas de double initialisation du vertex.

    Surtout, l'opérateur - unaire retourne un autre vertex, il n'a pas lieu de modifier l'objet.

    Concernant la compilation, une template n'est pas une classe. C'est un modèle pour que le compilateur puisse générer des classes (vertex<int>, vertex<double>, etc).
    Le compilateur a besoin de l'intégralité de la template pour cela.
    Tu peux éventuellement écrire les implémentations dans un second .h (parfois nommé .tpp), que tu inclues à la fin du premier.

  3. #3
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,
    Citation Envoyé par Luke spywoker Voir le message
    Quel est la meilleur solution d'implémentation a votre humble avis:

    1. un membre array de la classe Vertex et écrire tous l'overloading d'opérateur ?

    ou

    2. une classe Vertex héritant de la classe valarray, héritant de tous les bienfaits du valarray.
    De toutes façons, tu ne dois surtout pas utiliser l'héritage publique, car ta classe Vertex n'est ni un array ni un valarray au sens du LSP.

    De plus, ni std::array ni std::valarray ne sont prévus pour intervenir dans une relation d'héritage publique(leur destructeur est public et non virtuel)

    Tu peux éventuellement envisager l'héritage privé, pour indiquer que ton Vertex est "IMPLEMENTE SOUS LA FORME" d'un std::array / std::valarray, mais tu n'as a priori besoin d'accéder qu'aux fonctions membre publiques de ces classes et non à leurs fonctions membres protégées (y en a-t-il seulement ), ce qui réduit fortement l'intérêt d'un héritage quel qu'en soit la visibilité.

    Si bien que tu as tout aussi bon temps d'utiliser un std::array / std::valarray sous la forme d'un membre de ta classe

    Au passage: Tu ne dois AU GRAND JAMAIS mettre une directive using namespace std; dans un fichier d'en-tête car c'est typiquement le genre de directive qui se répandra comme un virus et qui finira à terme pas poser plus de problèmes qu'elle n'apporte de solutions.

    D'ailleurs, je suis même du genre à être plus virulent que cela vis à vis de cette directive (là, je viens de te donner le conseil "consensuel" ) et, si cela ne tenait qu'à moi, je te dirais volontiers que tu ne dois utiliser cette directive absolument nulle part en justifiant mon point de vue par le fait qu'elle a été mise en place pour permettre au code "pré normalisation" de continuer à fonctionner quand le comité a décidé de faire passer la bibliothèque standard dans l'espace de noms std.

    A part pour du code écrit à l'époque, il est bien plus utile (à mon sens du moins) de profiter de la capacité de séparer clairement les différentes fonctionnalités dans des espaces de noms différents, que de s'éviter l'écriture de cinq caractères de temps en temps
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Membre éprouvé
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Par défaut
    Merci pour vos conseils avisées,

    Je pensais que valarray était bien fait pour stocker des valeurs numériques, en outre la méthode shift() aurai été intéressant pour une classe Color.

    Tous les opérateurs sont déjà surchargés et en plus il y a une histoire avec le mot-clef restrict:
    ce qui permet des opérations sur ces classes d'optimiser semblable à l'effet du mot-clé restrict dans le langage de programmation C.
    Dommage seulement qu'il n'y ai pas d'accès au pointeur, comme vector<>.data(), sous-jacent...

    A méditer.


    Sinon j'ai déjà écrit une classe dérivé de pair() pour des coordonnées 2D (x -> first, y -> second).

    Merci pour le conseil concernant le namespace, je pense vraiment l'appliquer.

    Merci pour vos réponses éclairées.

  5. #5
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    Et l'option de réutiliser les classes de la bibliothèque standard plutôt que d'en faire une nouvelle, l'as-tu considérée? A voir l'interface de Vertex,
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    using Vertex = std::valarray<GL_UTILS_TYPE>;
    me paraîtrait tout à fait fonctionnel!
    Idem pour les coordonnées:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    using Coord2D = std::pair<GL_UTILS_TYPE, GL_UTILS_TYPE>

  6. #6
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par stendhal666 Voir le message
    Et l'option de réutiliser les classes de la bibliothèque standard plutôt que d'en faire une nouvelle, l'as-tu considérée? A voir l'interface de Vertex,
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    using Vertex = std::valarray<GL_UTILS_TYPE>;
    me paraîtrait tout à fait fonctionnel!
    Idem pour les coordonnées:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    using Coord2D = std::pair<GL_UTILS_TYPE, GL_UTILS_TYPE>
    Pour un vertex, cela peut effectivement s'envisager, mais pour une coordonnée (qu'elle soit 2D ou 3D), devoir jouer avec first/second (dans le cas d'une std::pair) ou get<0>/get<1>(/get<2>) dans le cas d'un tuple, cela me semble quand même moyen-moyen: typiquement les coordonnées représente l'axe des X, des Y (et des Z), et il serait dommage de retirer ce genre d'information

    Ceci dit, je ne verrais pas de problème à utiliser std::pair ou std::tuple (selon le cas) de manière sous-jacente... De toutes manières, une coordonnée devrait typiquement être utilisée de manière constante -- comme devraient en théorie l'être toutes les classes à sémantique de valeur -- vu que, si l'on change un tant soit peu la valeur de l'un des axes, on obtient bel et bien une coordonnée totalement différente
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 153
    Billets dans le blog
    4
    Par défaut
    Perso, pour une coordonnée (ou un vecteur, c'est strictement identique), j'ai toujours opté pour un simple POD
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     struct Vector {
      double x;
      double y;
      double z;
    };
    T'embellis de quelques helpers comme un constructeur, opérateurs etc et basta.
    Pour l'aspect "sémantique de valeur" etc, osef. C'est le programme qui doit être bien écrit et fournir le vector par const& ou copie quand il ne doit pas être modifié. Inutile de se compliquer la tâche, et btw il est toujours utile et (très) souvent nécessaire de ne modifier que la composante x de ta position. Rien de plus lourd que de devoir se taper une écriture position = Vector(position.x+1, position.y, position.z); au lieu d'un trivial position.x += 1;. C'est lourd, moche, moins lisible et n'apporte rien. C'est un élément simple, qu'on manipule simplement, et régulièrement, alors faisons simple!
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Vertex arrays
    Par goutbouyo dans le forum OpenGL
    Réponses: 9
    Dernier message: 06/01/2005, 13h11
  2. classe Vertex
    Par nicolas66 dans le forum OpenGL
    Réponses: 21
    Dernier message: 26/11/2004, 23h19
  3. [SDL+glut] vertex array précompilés
    Par khayyam90 dans le forum OpenGL
    Réponses: 3
    Dernier message: 01/10/2004, 17h07
  4. vertex array
    Par Jbx 2.0b dans le forum OpenGL
    Réponses: 2
    Dernier message: 12/07/2004, 11h37
  5. Performance des vertex array
    Par Mathieu.J dans le forum OpenGL
    Réponses: 13
    Dernier message: 25/06/2004, 10h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo