Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème typeid

    19 juin 2008 à 19:14:25

    Bonjour

    Voici la méthode de ma classe matrice qui pose problème :

    template<class truc> void matrice<truc>::afficher( void )
    {
    	if(strcmp(typeid(m1).name(),"class matrice<complexe>")==0)
    	{
    		(*this)[i][j].afficher();
    	}
    	else
    	{
    		cout<<(*this)[i][j];
    	}
    }
    


    (*this)[i][j] est un truc (élément de la ième ligne jème colonne de ma matrice de trucs) truc = complexe ou int

    Mon problème est le suivant, seul la classe complexe possède la méthode afficher ce qui ne devrait pas poser de problème étant donné le if(strcmp(typeid(m1).name(),"class matrice<complexe>")==0).
    Mais le compilateur m'affiche l'erreur suivante :

    error C2228: la partie gauche de '.afficher' doit avoir un class/struct/union

    Il semblerait qu'il essaye d'effectuer (*this)[i][j].afficher() lorsque (*this)[i][j] est un int et donc il n'y arrive pas...

    J'ai eu beau chercher je ne trouve pas de solutions.



    • Partager sur Facebook
    • Partager sur Twitter
      19 juin 2008 à 19:18:58

      Ce n'est pas comme cela que l'on spécialise du comportement au milieu de templates.
      Tu ferais mieux de définir une police qui part défaut balance sur cout, et qui dans le cas des complexe utilise leur fonction afficher() -- par spécialisation template.


      (Mais le mieux est encore définitivement de supporter l'injection vers flux (operator<<) sur ta classe complexe ; et de ne jamais parasiter du code métier de fonctions membre qui s'appellent afficher() et qui attaquent directement un flux global comme std::cout)
      • Partager sur Facebook
      • Partager sur Twitter
      C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
        19 juin 2008 à 19:20:33

        Ce n'est pas un if qui empêchera les deux parties du code d'être compilé pour tous les types, et donc de générer tout un tas d'erreurs de compilation.

        Lorsque tu veux exécuter tu code différent selon un type, cela s'appelle de la meta-programmation et cela utilise entre autres la spécialisation de templates. Je te laisse lire quelques bons tutos à ce sujet ;)

        De plus, typeid().name() retourne tout sauf quelque chose de standard ; tu ne peux pas être certain que pour un type donné cela sortira la même chaîne sur tous les compilos (cela peut même varier pour un même compilo).

        A part ça... pourquoi est-ce que ton type complexe ne possède pas plutôt une surcharge de l'opérateur << ? Je pense que ce serait la vraie bonne solution ici.
        • Partager sur Facebook
        • Partager sur Twitter
          19 juin 2008 à 19:33:20

          J'utilise l'opérateur << pour écrire dans des fichiers de sauvegarde qui seront relus par la suite.
          Le complexe 2+i est donc affiché 2 1 avec cout.
          Je souhaiterai utiliser une méthode afficher pour que mon complexe ressorte comme 2+i à l'écran (ce qui serait plus propre).
          Je vais donc essayer de me renseigner sur la meta-programmation.

          Merci pour ces réponses rapide.
          • Partager sur Facebook
          • Partager sur Twitter
            19 juin 2008 à 20:03:19

            Pourquoi la méta-programmation ici ? une spécialisation du template devrait suffire.

            J'ai pas bien compris ce que tu avais fait avec l'opérateur <<.
            • Partager sur Facebook
            • Partager sur Twitter
            Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
              19 juin 2008 à 20:20:12

              template<class truc> 
              void matrice<truc>::afficher( void )
              {
                  std::cout << (*this)[i][j];
              }
              
              template<> 
              void matrice<complexe>::afficher( void )
              {
                  (*this)[i][j].afficher();
              }
              


              D'où vient i et j ?

              Conseil : Regarde du côté de la surcharge de l'opérateur << puis retire les méthodes afficher() de _toute_ tes classes.

              P.S. pas de using namespace std; dans les en-têtes.
              • Partager sur Facebook
              • Partager sur Twitter
                19 juin 2008 à 21:36:16

                Pour i et j : je n'ai mis que la partis qui nous intéresse pour mon problème, normalement il y a deux boucles for...

                Que dois-je mettre dans les fichier en-tête?

                Cette erreur s'affiche quand je recompile :

                error LNK2005: "public: void __thiscall matrice<class complexe>::afficher(void)" (?afficher@?$matrice@Vcomplexe@@@@QAEXXZ) déjà défini(e) dans matrice.obj

                P.S. : je ne comprend pas se que tu as voulus dire dans ton P.S.
                Quel est le problème avec using namespace std;
                • Partager sur Facebook
                • Partager sur Twitter
                Anonyme
                  19 juin 2008 à 22:13:00

                  dans les entete on met std:: partout, il n'y a que dans les .cpp qu'on met using namespace std;
                  mais ce n'est qu'une convention(je crois)
                  • Partager sur Facebook
                  • Partager sur Twitter
                    19 juin 2008 à 22:19:59

                    Réponses aux 2 questions dans la FAQ de developpez.
                    • Partager sur Facebook
                    • Partager sur Twitter
                    C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                      19 juin 2008 à 22:36:52

                      Citation : Pas de titre

                      Réponses aux 2 questions dans la FAQ de developpez.



                      Désolé j'ai pas trouvé mes réponses...

                      Pour ce qui est de mon fichier en-tête je ne sais pas quoi mettre et où le mettre?

                      J'ai mis :
                      template<>
                      void matrice<complexe>::afficher( void );

                      avec les spécification des foncions et procédures mais ça m'a mis l'erreur de tout à l'heure.

                      Et pour ce qui est de using namespace std; il est dans un seul fichier d'entête et j'ai jamais eu de problème...

                      Je suis perdu please help me.

                      Merci.

                      • Partager sur Facebook
                      • Partager sur Twitter
                        19 juin 2008 à 22:57:31

                        D'après ce que j'ai compris, si je veux utiliser la spécialisation de template il faut que je redéfinisse la casi totalité de mes méthodes.
                        Ceci me parait un peu trop pour un simple affichage, tant pis je crois que je vais garder avec mon affichage simple avec des cout...

                        A moins que quelqu'un ai une idée plus simple?

                        Merci à tous pour votre aide.
                        • Partager sur Facebook
                        • Partager sur Twitter
                          20 juin 2008 à 1:18:12

                          Citation : Dénissss

                          D'après ce que j'ai compris, si je veux utiliser la spécialisation de template il faut que je redéfinisse la quasi totalité de mes méthodes.


                          Absolument pas.
                          template <typename Number> struct NumberWriter {
                              static std::ostream display(std::ostream &os, Number const& n) {
                                  return os << n;
                              }
                          };
                          
                          template <> struct NumberWriter<Complexe> {
                              static std::ostream display(std::ostream &os, Complexe const& c) {
                                  return os << c.re() << "+" << c.im() << "i";
                              }
                          };
                          
                          ....
                          template <typename Number> struct Matrice {
                              std::ostream & display(std::ostream & os) const {
                                  for x2 { {
                                      NumberWriter<Number>::display(os, m_buffer[i][j]) << ' ';
                                  }}
                                  return os;
                              }
                          };
                          


                          NB: on peut aussi sortir les traits (http://www.angelikalanger.com/Articles/C++Report/IteratorsInStdlib/IteratorsInStdlib.html)
                          • Partager sur Facebook
                          • Partager sur Twitter
                          C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                            20 juin 2008 à 12:22:50

                            Le truc c'est que j'utilise l'opérateur[] dans ma méthode afficher.
                            Il faut donc que je le redéfinisse dans :

                            template < > class   matrice 
                            {
                                   void afficher( void )
                                   {
                                   ...
                                   }
                            };
                            

                            N'es-ce pas?

                            Et l'opérateur[] utilise lui même d'autres méhodes...

                            Il faudrait donc que je redéfinisse tous ça ce qui me ferais perdre l'utilité de la généricité.

                            Je pense que je vais créer une procédure en plus de la méthode afficher de matrice on aura donc :

                            template <truc> void afficher( truc t )
                            {
                            cout<<t;
                            }
                            template < > void afficher( complexe c )
                            {
                            c.afficher();
                            }
                            


                            Et là on a plus besoin de redéfinir les outils utilisé dans afficher.

                            Es-ce que ça vous semble correct?


                            • Partager sur Facebook
                            • Partager sur Twitter
                              20 juin 2008 à 12:25:18

                              Dans ta classe Matrice, tu devrais plutôt surcharger l'opérateur() de sorte que tu puisses directement renvoyer la valeur contenue dans la case x,y et pas une colonne (ligne ?) de la matrice.

                              L'opérateur << sera alors très simple à définir.
                              • Partager sur Facebook
                              • Partager sur Twitter
                              Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
                                20 juin 2008 à 13:07:46

                                Y a un truc que je comprend pas bien la... voici ce que j'ai ajouté a mon programme :

                                template<class truc> void afficher_truc( const truc & t )
                                {
                                	cout<<t;
                                }
                                
                                template<>
                                void afficher_truc<class complexe>( const complexe & c )
                                {
                                	complexe c1=c;          // car c.afficher() ne marche pas c étant une constante
                                	c1.afficher();
                                }
                                



                                Apriori comme ce qui était indiqué au lien suivant :
                                http://cpp.developpez.com/faq/cpp/?pag [...] pecialisation

                                Mais mon compilateur me met l'erreur suivante :

                                Test.obj : error LNK2005: "void __cdecl afficher_truc<class complexe>(class complexe const &)" (??$afficher_truc@Vcomplexe@@@@YAXABVcomplexe@@@Z) déjà défini(e) dans matrice.obj


                                Je comprend pas ce qui se qu'il faut faire pour y remédier...
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  20 juin 2008 à 13:46:29

                                  afficher() modifie l'objet que tu affiches ?
                                  Non!
                                  Donc mets la fonction constante. (Ce n'est pas pour dire, mais aucune des signatures que j'ai données n'a été le fruit du hasard ou de cours bâclés que j'ai suivi aveuglément)
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                  C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                                    20 juin 2008 à 14:13:02

                                    Bon sur ce je crois que je vais m'arrêter là, tous ça me dépasse un peu. Et je dois rendre mon projet...
                                    J'essayerai de comprendre ça quand j'aurai un peu plus de temps.

                                    En tous cas merci à tous pour vos renseignements, même si j'ai pas toujours tout bien compris ;)
                                    • Partager sur Facebook
                                    • Partager sur Twitter

                                    Problème typeid

                                    × 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