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

Langage C++ Discussion :

Méthode template dans classe non template ?


Sujet :

Langage C++

  1. #1
    Expert confirmé
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 524
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 184
    Points
    5 184
    Par défaut Méthode template dans classe non template ?
    Bonjour,

    je me suis créé une classe pour gérer de manière souple des messages d'exception :
    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
    // exception de base
    class exception_base : public std::exception
    {
    public: // methodes publiques
    	exception_base(void);
    	exception_base(exception_base& e);
    	virtual ~exception_base(void);
    
    
    	// operateurs de flux
    	exception_base& operator<<(const char* s);
    	exception_base& operator<<(const int& v);
    	exception_base& operator<<(const unsigned int& v);
    
    	// recuperation du message d'erreur
    	std::string Message(void);
    
    
    protected: // donnees protegees
    	std::ostringstream			m_sMessage;
    };
    vous remarquerez en gras les opérateurs de flux pour envoyer un int et un unsigned int dans le flux

    j'aimerai savoir s'il y a un moyen de templater l'opérateur ou si je vais devoir (re)définir tous les opérateurs qui me sont nécessaires

    en passant, si vous avez des commentaires/critiques sur cette classe n'hésitez pas à m'en faire part
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  2. #2
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Oui, tu peux sans problèmes définir des membres templates dans une classe non template, à condition que les membres ne soient pas virtuels.

    Mais la méthode habituelle pour optenir les opérateurs d'insertion, c'est d'hériter de ostream en ayant défini son propre streambuf. Il y a un exemple dans la FAQ de fclc++.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  3. #3
    Expert confirmé
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 524
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 184
    Points
    5 184
    Par défaut
    merci pour le lien, je vais aller y jeter un oeil

    de mon côté j'ai ajouté la méthode suivante à ma classe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<class T>exception_base& operator <<(const T& something)
    {
    	m_sMessage << something;
    	return *this;
    }
    est-ce une bonne solution ?

    en tout cas ça fonctionne , à condition que je déclare toute la méthode dans le .h
    je ne comprend pas pourquoi je ne peux prototyper la méthode dans le .h et la déclarer dans le .cpp sans avoir d'erreurs de liens non résolus
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  4. #4
    Membre éprouvé

    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2005
    Messages
    634
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2005
    Messages : 634
    Points : 1 205
    Points
    1 205
    Par défaut
    Citation Envoyé par shenron666
    je ne comprend pas pourquoi je ne peux prototyper la méthode dans le .h et la déclarer dans le .cpp sans avoir d'erreurs de liens non résolus
    http://c.developpez.com/faq/cpp/?pag...VERS_templates
    Fiquet
    - FAQ SDL
    - FAQ C++

  5. #5
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    en tout cas ça fonctionne
    Tu ne pourras pas injecter de manipulateurs (std::endl par exemple).

  6. #6
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par shenron666
    je ne comprend pas pourquoi je ne peux prototyper la méthode dans le .h et la déclarer dans le .cpp sans avoir d'erreurs de liens non résolus
    Il y a moyen, mais les compilateurs qui supportent ça sont rares. Il faut utiliser export (liens vers un texte en anglais).
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  7. #7
    Expert confirmé
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 524
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 184
    Points
    5 184
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    Mais la méthode habituelle pour optenir les opérateurs d'insertion, c'est d'hériter de ostream en ayant défini son propre streambuf. Il y a un exemple dans la FAQ de fclc++.
    je n'ai rien trouvé sur fclc++ me permettant d'aboutir et en même temps je voudrais éviter d'hériter de ostream
    mais si tu as un exemple je prend, parcequ'il semble impossible de lever une exception basée sur ostream

    Citation Envoyé par Laurent Gomila
    Tu ne pourras pas injecter de manipulateurs (std::endl par exemple).
    même si c'est plutot secondaire pour une simple classe exception, tu pourrais m'aider que je vois comment faire dans ce cas ?
    j'ai essayé différentes surcharges en friend également mais je ne sais pas comment conaitre les bons paramètres à utiliser (type de retour et paramètres à passer)
    je pense que ça pourrais au moins être utile pour apprentissage sinon pour une classe de log
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  8. #8
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    même si c'est plutot secondaire pour une simple classe exception, tu pourrais m'aider que je vois comment faire dans ce cas ?
    j'ai essayé différentes surcharges en friend également mais je ne sais pas comment conaitre les bons paramètres à utiliser (type de retour et paramètres à passer)
    Je ne me rappelle plus du prototype exact, sûrement une fonction prenant un ostream en paramètre. Cherche dans les en-têtes la surcharge de << qui prend ce genre de manipulateur.
    Mais de toute façon, comme déjà dit il vaudra mieux implémenter ton propre streambuf

  9. #9
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par shenron666
    il semble impossible de lever une exception basée sur ostream
    Normal, les exceptions doivent être copiables, et ostream ne l'est pas.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  10. #10
    Expert confirmé
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 524
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 184
    Points
    5 184
    Par défaut
    Citation Envoyé par Laurent Gomila
    Je ne me rappelle plus du prototype exact, sûrement une fonction prenant un ostream en paramètre. Cherche dans les en-têtes la surcharge de << qui prend ce genre de manipulateur.
    en fait, l'erreur du compilateur indique qu'il lui faut une fonction surchargée en paramètre :
    main.cpp(15): error C2679: '<<' binaire*: aucun opérateur trouvé qui accepte un opérande de partie droite de type 'overloaded-function' (ou il n'existe pas de conversion acceptable)
    J'ai donc implémenté cette méthode :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    exception_base& operator<<(std::ostream& (__cdecl *_Pfn)(std::ostream&))
    {
    	((*_Pfn)(m_sMessage));
    	return *this;
    }
    ce qui me permet de générer une exception de la manière suivante (programme de test) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    try {
    	char* filename = "config.cfg";
     
    	THROW_EXCEPTIONMESSAGE(std::endl << "Fichier \"" << filename << "\" introuvable" << std::endl);
    } catch (exception_base& e) {
    	std::cout << e.Message();// << std::endl;
    }
    j'ai créé les defines suivants pour me simplifier la vie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #define SOURCE_LOCATION				" dans " << __FILE__ << "(" << __LINE__ << ")"
    #define THROW_SIMPLEEXCEPTION			throw (exception_base() << SOURCE_LOCATION);
    #define THROW_EXCEPTIONMESSAGE(msg)		throw (exception_base() << SOURCE_LOCATION << " : " << msg);
    Le contructeur de exception_base initialisant m_sMessage avec "Exception", j'obtient la sortie suivante :
    Exception dans main.cpp(15) :
    Fichier "config.cfg" introuvable
    [EDIT] Je met en résolu vu que ça fonctionne au moins comme je le souhaitait
    et pour ceux qui veulent le code source complet, je le joint en zip (voir mon dernier post)
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Les flux sur opérateur nécessitent deux argument, quand on les déclare...

    Typiquement, cela se fait sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    ostram& operator<<(ostream& flux,TaClasse &objet)
    {
        flux<<objet.membre<<" "
             <<objet.membre2;
        returnt flux;
    }
    en prenant soin de veiller à ce que membre et memre2 soient, eux meme, compatible avec l'opérateur <<

    D'un autre coté, je suis quelque peu surpris que ton compilateur ne t'indique ni erreur ni avertissement concernant le destructeur de ta classe...

    En effet, le prototype du destructeur d'une std::exception est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    exception::~exception()throw
    de manière à lui interdire de lancer lui meme une exception...

    Dans un projet un peu complexe, j'avais été jusqu'à créer une foule de nouvelles exception, que je délarais comme ceci:
    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
     
    //////////////////////////////////////////////////////////////////////////////
    //                    classe de base de toutes les exception                //
    //////////////////////////////////////////////////////////////////////////////
    class CException : public std::exception
    {
        private:
            //l'utilisation de tableau de char devrait etre systématiquement
            //refusée
            const char * what()const throw(){return m_Message.c_str();};
        protected:
            std::string m_Message;
            void Rapport();
        public:
            // class constructor
            CException(){};
            // class destructor
            ~CException() throw(){};
    };
    struct CTailleNulle:public CException
    {
        CTailleNulle(const std::string &fichier, int ligne);
    };
    (exemple d'une demande d'allocation de taille nulle)
    et qui était implémentée sous la forme de
    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
     
    void CException::Rapport()
    {
        std::ofstream ofs;
        ofs.open("rapportexception.log",std::ofstream::out|std::ofstream::app);
        ofs<<m_Message;
        ofs.close();
    }
    CTailleNulle::CTailleNulle(const std::string &fichier, int ligne)
    {
        std::ostringstream oss;
        oss<<"tentative d'allocation d'une taille nulle pour un pointeur dans "
        <<fichier<<" ligne "<<ligne<<std::endl;
    #ifdef ENABLESCREEN
        std::cout<<oss.str();
        std::cin.get();
    #endif
        m_Message=oss.str();
        Rapport();
    }
    La méthode Rapport() écrivant le message à la fin d'un fichier log, et ENABLESCREEN permettant de déterminer si le message devait apparaitre à l'écran...

    L'appelle de l'exception se faisait sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    if(test risquant de mal tourner)
        throw CTailleNulle(__FILE__,__LINE__);
    Suite à ==>une question sur le forum<== (qui n'avait pas grand chose avec la tienne), j'ai placé une archive avec un code source dans lequel toute une série d'exceptions sont déclarées
    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

  12. #12
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Les flux sur opérateur nécessitent deux argument, quand on les déclare...
    Dans le cas d'une fonction membre, le premier paramètre est *this et le second est en fait le premier argument.
    On a donc bien deux paramètres pour l'opérateur<< qui est binaire.
    Boost ftw

  13. #13
    Expert confirmé
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 524
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 184
    Points
    5 184
    Par défaut
    Citation Envoyé par koala01
    Salut,

    Les flux sur opérateur nécessitent deux argument, quand on les déclare...
    je comprend de quoi tu parles, mais ma méthode est interne à la classe
    n'est-ce pas uniquement dans une méthode déclarée friend que ce cas s'impose ?

    D'un autre coté, je suis quelque peu surpris que ton compilateur ne t'indique ni erreur ni avertissement concernant le destructeur de ta classe...
    bah... c'est visual c++ 7.1 alors tu sais les erreurs et warning... il en oublie un peu

    En effet, le prototype du destructeur d'une std::exception est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    exception::~exception()throw
    de manière à lui interdire de lancer lui meme une exception...
    je corrige ça tout de suite, je retire le zip que j'ai mis dans le post précédente et je met la nouvelle version ici

    Suite à ==>une question sur le forum<== (qui n'avait pas grand chose avec la tienne), j'ai placé une archive avec un code source dans lequel toute une série d'exceptions sont déclarées
    je vais aller voir ça de ce pas, merci pour le lien
    Fichiers attachés Fichiers attachés
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

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

Discussions similaires

  1. Réponses: 18
    Dernier message: 01/03/2012, 10h34
  2. Réponses: 6
    Dernier message: 21/07/2009, 13h53
  3. Réponses: 3
    Dernier message: 09/04/2009, 11h30
  4. Réponses: 3
    Dernier message: 08/07/2008, 15h06
  5. Réponses: 9
    Dernier message: 19/05/2007, 15h28

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