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 :

Template et fonction amie / type de retour inconnu


Sujet :

C++

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 28
    Points : 10
    Points
    10
    Par défaut Template et fonction amie / type de retour inconnu
    Bonjour à tous !

    J'ai besoin de vous pour un projet de la fac, je dois faire un logiciel de retouche d'image sur le format ppm.

    J'ai un soucis au niveau de ma classe image qui est un template : elle contient des fonctions amies et G++ me signal ca comme potentiellement anormale, j'ai un peu peur que lors du teste du programme, tout plante à cause d'une mauvaise declaration de ma part du coup ...

    Voici comme j'ai fait :

    __________.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    #include <iostream>
     
    template<int N>
    class image
    {
      mes_attribut;
    public:
     //fct amie
      friend void save(image, std::string);
    };
    __________.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #include <iostream>
     
    template<int N>
    void save(image<N> pic, std::string path)
    {}
    l'erreur est
    "friend declaration 'void save(image<N>, str::string)' declares a non-template function"
    "if this is not what you intended, make sur the function template has already been declared and add <> after the function name here"


    Mon second problème viens du type des images, les images PPM peuvent être des images en noir et blancs (P1) ou couleur(P3), j'ai personnelement choisi de developper une classe "base" qui représente une matrice de nombres, puis image qui est un tableau de N base. Aucun soucis pour ça, SAUF pour le bouton "ouvrir". Bah voui, je sais pas à l'avance si c'est un P1 ou un P3, donc le type de retour de "ouvrir", je le connais pas ...

    J'ai vu sur le net qu'on pouvais utiliser comme type de retour, un mot clé "object", mais je n'ai trouvé aucun exemple ... un peu d'aide svp ?


    Merci d'avance !!

  2. #2
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2011
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2011
    Messages : 29
    Points : 63
    Points
    63
    Par défaut
    Salut, essaye :

    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
     
    template <typename N>
    class image
    {
     
    public:
     
    	template <typename T>
      friend void save(image<T>, std::string);
    };
     
     
    template <typename N>
    void save(image<N> pic, std::string path)
    {}
    pour voir.

  3. #3
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    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 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Attention, il y a une autre possibilité, qui ne déclare que la fonction prenant la meme template comme friend.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    template <typename N> struct image {
    	template <>
    	friend void save(image<N>, std::string);
    }
    j'ai juste un doute sur la syntaxe, entre image<N> ou image?
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  4. #4
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2011
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2011
    Messages : 29
    Points : 63
    Points
    63
    Par défaut
    Attention, il y a une autre possibilité, qui ne déclare que la fonction prenant la meme template comme friend.
    Bien vu, dans ce cas j'enlèverais effectivement le <N> de image dans la déclaration "interne" de de save car implicite (après peut-être que les deux marche), et par contre je pense qu'il faut mettre

    En gros :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    template <typename N>
    class image
    {
     
    public:
     
    		template <typename>
    		friend void save(image, std::string);
    };
     
     
    template <typename N>
    void save(image<N> pic, std::string path)
    {}
    Et si ça ne passe pas, il faut remplacer

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    friend void save(image, std::string);
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    friend void save(image<N>, std::string);
    mais là j'avoue que je ne sais pas par cœur.

  5. #5
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 28
    Points : 10
    Points
    10
    Par défaut
    Pourquoi un "template <typename>" en fait ? je comprend pas

    Et vous avez une idée pour mon second problème ? ^^


    Ps: l'erreur n'est plus

  6. #6
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    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 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Je ne pense pas qu'il faille un typename. Sans nom de type derrière, ca me parait … incongru.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  7. #7
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 28
    Points : 10
    Points
    10
    Par défaut
    Sans "typename" (juste avec "<>") ça marche pas ^^

    Et au final, j'ai des plus gros problèmes maintenant ... seg fault ...

    Pour représenter mes images, voila comment je fait :

    1) une classe "base" (en fait c'est une matrice)
    2) un template<int N> "image" qui n'est qu'un tableau de base (un matrice en 3D du coup, pour pouvoir représenter de 1 (si c'est une image noir/blanc) à 3 (pour RGB) "couleurs)).

    Je vous montre les parties du codes ou j'ai surement un problème :

    MAIN
    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
     
    #include "image.hpp"
    #include "base.hpp"
    #include <cstdlib>
    #include <iostream>
    #include <ctime>
    #include <cmath>
    #include <fstream>
    #include <string>
     
    int main()
    {
    	const string load = "./zozo.ppm";
    	const string save = "./test2.ppm";
     
    	image<3> a(load);
    	//a.save(save);
     
    	return 0;
    }
    classe BASE.cpp
    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
     
    base::base(int lin, int col)
    {
    	l=lin;
    	c=col;
     
    	matrice = new int*[lin];
     
    	for(int i=0; i<lin; i++)
    	{
    		matrice[i] = new int[col];
    		for(int j=0; j<col; j++)
    			matrice[i][j] = 0;
    	}
    }
     
    base::~base()
    {
    	for(int i=0; i<l; i++)
    		delete [] matrice[i];
     
    	delete[] matrice;
    }
     
     
    int* base::operator[](int i)
    {
    	return matrice[i];
    }
    classe BASE.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class base
    {
    	int l, c;
    	int** matrice;
     
    	public:
    		base(int, int);
    		~base();
    		int* operator[](int);	
    };
    classe template IMAGE.hpp
    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
     
    #include <iostream>
    #include "base.hpp"
    #include <cstdlib>
    #include <assert.h>
    #include <iostream>
    #include <string>
    #include <fstream>
     
    using namespace std;
     
    template <int N>
    class image
    {
    	int line;
    	int col;
    	int dimension;
    	string p;
    	int nb_color;
     
    	base* img[N];	
     
    	public:
    		image(string);
                    ~image();
    		base& operator[](int);
    };
     
    template <int N>
    image<N>::image(string path)
    {
    	ifstream fichier;
    	fichier.open(path.c_str());
     
    	if(fichier)
    	{
    		getline(fichier, p);
     
    		fichier >> col;
    		fichier >> line;
    		dimension = N;
     
    		if( ! (p == "P1" || p == "P4"))
    			fichier >> nb_color;
    		else
    			nb_color = 2;
     
    		int i, j, k;	
     
    		for(i=0; i<N; i++)
    			img[i] = new base(line, col);
     
    		cout << p << endl << line << endl << col << endl << dimension << endl;
     
    		for(j=0; j<line; j++)
    		{
    			for(k=0; k<col; k++)
    			{
    				for(i=0; i<N; i++)
    				{
    					fichier >> *this[i][j][k];
    				}
    			}
    		}
     
    		fichier.close();		
    	}
    }
     
    template <int N>
    image<N>::~image()
    {delete[] img;}
     
     
    template <int N>
    base& image<N>::operator[](int i)
    {
    	return *(img[i]);
    }
    D'après GDB, c'est au niveau de l'operator [], mais je vois pas quoi ... merci d'avance

  8. #8
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    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 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Bonjour,

    D'abord, deux horreurs, qui rendront to code nocif:
    pas de using namespace std;
    pas de garde contre les inclusions multiples (#define/#ifndef/code/#endif)

    tu inclues tes en-têtes avant les standards, donc ton "using namespace std::" est injecté dedans, posant potentiellement des soucis...

    Enfin, un problème de conception: int* matrice::operator[](int).
    C'est assez grave pour que nous ayons deux entrées à ce sujet dans la faq:
    comment indexer une matrice
    pourquoi indexer une matrice avec operator()

    Quelque chose me chiffonne avec ton code.
    Pourquoi ne parviens-tu pas a avoir une classe de matrice qui soit une valeur.
    Je veux dire "Comment ce fait-il que tu sois obligé d'utiliser un tableau de pointeur de matrices?"
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  9. #9
    Membre expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Points : 3 892
    Points
    3 892
    Par défaut
    Pour la segfault, c'est tout simple : tu as fais des new et tu fais des delete[], il faut choisir tout l'un ou tout l'autre : new[]+delete[] ou new+delete, mais pas un mix.

    Pour le reste +1 leternel.

  10. #10
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 28
    Points : 10
    Points
    10
    Par défaut
    J'ai déjà des ifndef/endif dans mes .h, je ne les ai pas mit pour alléger un peu ^^ pour le std, je savais pas ... il vaut mieux utiliser systématique std:: alors ?

    D'après ce que je lit sur la faq, il faudrai que j'abandonne ma matrice au profit d'un tableau pour suivre ce qui se passe dans la mémoire ?


    J'ai changé mon base* img [N]; en base* img;.

    je fait un seul new : img = new base[N] puis un delete : delete[] img;.

    Je mélange pas, mais j'ai quand même des erreurs

    ça viens de mon operator=, j'en suis presque sur ! ^^

    Operator= d'image
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    template<int N>
    image<N>& image<N>::operator=(image& i)
    {
     //je delete l'image pour la réalloué après
    delete[] img;
    ...
     
    img = new base[i.dimension];
     
    for(int m = 0; m<i.dimension; i++)
    img[m]=i[m];
    }
    operator= de base
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    base base::operator=(base& b)
    {
    for(int i=0; i<l; i++)
    delete[] matrice[i];
     
    delete[] matrice;
    ...
     
    matrice = new int*[b.l];
     
    for(int i = 0; i<b.l; i++)
    matrice[i] = new int[b.c];
    }

  11. #11
    Membre expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Points : 3 892
    Points
    3 892
    Par défaut
    Dans le constructeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for(i=0; i<N; i++)
    			img[i] = new base(line, col);
    Dans le destructeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template <int N>
    image<N>::~image()
    {delete[] img;}

  12. #12
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 28
    Points : 10
    Points
    10
    Par défaut
    En modifiant en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    template <int N>
    image<N>::~image()
    {for(int i=0; i<N; i++)
        delete img[i];}
    ça ne marche pas plus

  13. #13
    Membre expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Points : 3 892
    Points
    3 892
    Par défaut
    Il faut également changer les new[] de tous tes opérateurs en for+new

  14. #14
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 28
    Points : 10
    Points
    10
    Par défaut
    Citation Envoyé par germinolegrand Voir le message
    Il faut également changer les new[] de tous tes opérateurs en for+new
    Je ne comprend pas ce que tu veux dire :/

Discussions similaires

  1. Réponses: 25
    Dernier message: 04/06/2012, 22h02
  2. Réponses: 32
    Dernier message: 28/11/2010, 17h33
  3. class template et fonction amie
    Par sleepless dans le forum C++
    Réponses: 5
    Dernier message: 19/11/2010, 13h37
  4. Type de retour inconnu
    Par tittoto dans le forum C++
    Réponses: 4
    Dernier message: 04/12/2008, 12h29
  5. type de retour de fonction template
    Par k1000 dans le forum Langage
    Réponses: 5
    Dernier message: 21/04/2008, 11h41

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