Probleme threads [Résolu]

Signaler
Messages postés
492
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
12 janvier 2012
-
Messages postés
694
Date d'inscription
lundi 5 décembre 2005
Statut
Membre
Dernière intervention
8 janvier 2014
-
Bonjour,
je n'arrive pas à compiler ce petit programme servant a illustrer mon problème :

<hr size="2" width="100%">#include
#include

using namespace std;

static pthread_mutex_t mutex;

struct Foo
{
string f;
Foo();
~Foo();
void* affiche(void *p_data);
};

Foo::Foo ()
{
string tmp("Je suis Foo");
f=tmp;
}

Foo::~Foo()
{ }

void* Foo::affiche(void *p_data)
{
cout << f << endl;
return NULL;
}

int main()
{
pthread_mutex_init (&mutex, NULL);

pthread_t thrd1;

Foo f;

pthread_create(&thrd1,NULL,f.affiche,NULL);

pthread_join(thrd1, NULL);

cout << "Fin" << endl;

return 0;
}
<hr size="2" width="100%">
Ce programme ne fait pas grand chose, il sert juste d'illustration au problème que je rencontre.

Pourquoi le compilo me dit-il : fichier.cpp:40: error: argument of type `void*(Foo::)(void*)' does not match `void*(*)(void*)'
Et comment résoudre mon problème.
D'avance merci !

TuRn3r

18 réponses

Messages postés
694
Date d'inscription
lundi 5 décembre 2005
Statut
Membre
Dernière intervention
8 janvier 2014
15
Il s'agit d'un problème de transtypage, mais je ne vois pas trop non plus. pcreate_thread ne semble pas aimer les parametres de type fonction membre ou le transtypage n'est pas écrit correctement.
Il doit y avoir un moyen de forcer mais je ne vois pas. désolé.

essayes ça : c'est pas la bonne solution mais ça compile semble-t-il

void * p (void *t) {
((Foo *)t)->affiche(t);
}

int main()
{
pthread_mutex_init (&mutex, NULL);

pthread_t thrd1;

Foo f;
pthread_create(&thrd1,NULL,p,(void *)&f);

pthread_join(thrd1, NULL);

cout << "Fin" << endl;

return 0;
}

Par contre si quelqu'un comprend son problème je suis aussi preneur !
Messages postés
20
Date d'inscription
vendredi 16 mai 2003
Statut
Membre
Dernière intervention
29 septembre 2006

[auteurdetail.aspx?ID= 638418 AlexN]-> structure et classe c'est la même chose comme l'a expliqué [auteurdetail.aspx?ID=304809 turnerom] mis à part la valeur par défaut d'accès qui est dans un cas est public et dans l'autre est privé; et une fonction membre ayant pour nom le nom de la structure, est bien un constructeur de la stucture, de même que la structure peut avoir un destructeur, etc...

[auteurdetail.aspx?ID=304809 turnerom]: Concernant l'erreur, elle vient du fait que tu passes l'adresse d'une fonction membre de structure Foo `void*(Foo::)(void*)' alors que la fonction pthread_create attend l'adresse d'un fonction simple `void*(*)(void*)'. En simplifiant pour le compilateur, l'appel d'une fonction membre se fait comme l'appel d'une fonction simple mais avec en plus la transmission d'un paramètre supplémentaire (et caché) qui est le pointeur sur la (structure ou la classe): C'est le fameux 'this'. C'est comme cela que se fait le lien entre les fonctions membre de l'objet et les données de l'objet. Il me semble d'ailleurs que les 1er compilateurs C++ ne permettait pas d'obtenir l'adresse d'une fonction membre, ce qui n'était pas plus mal car l'adresse d'une fonction membre sans l'adresse de l'instance de la classe à laquelle elle appartient n'est pas utilisable sauf en assembleur puisque la on peut rajouter le pointeur (this) sur la pile.

La solution d'[auteurdetail.aspx?ID =638418 AlexN] est donc exacte. On aurait pu parvenir au même résultat, en rendant la fonctions affiche static et la le paramètre void *p_data avait une utilité
Messages postés
492
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
12 janvier 2012
1
Toute petite précision :
ne pas oublier

void * p (void *t) {
((Foo *)t)->affiche(t);
return NULL;
}

Ca ne sert à rien, je sais, mais ca évite au compilo de gueuler.

TuRn3r
Messages postés
492
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
12 janvier 2012
1
Sinon,
s'il y a encore un peu de monde dans le coin, voila comment faire beaucoup (!!!) plus simple avec BOOST:

<hr size="2" width="100%">#include
#include

using namespace std;
using namespace boost;

struct Foo
{
string f;
string m_nom;
Foo(const string nom);
~Foo();
void operator()();
};

Foo::Foo (const string nom)
:m_nom(nom)
{
string tmp("Je suis Foo");
f=tmp;
}

Foo::~Foo()
{ }

void Foo::operator()()
{
cout << m_nom << " : " << f << endl;
}

int main()
{
thread thrd1(Foo("Bob"));

thrd1.join();

cout << "Fin" << endl;

return 0;
}

<hr size="2" width="100%">
TuRn3r
Messages postés
694
Date d'inscription
lundi 5 décembre 2005
Statut
Membre
Dernière intervention
8 janvier 2014
15
c'est pas class Foo que tu voulais écrire au lieu de struct Foo ?
Messages postés
987
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
30 août 2012
24
Peux etre que ca vient du faite que Foo est une structure et pas une classe
++
Messages postés
987
Date d'inscription
mardi 31 mai 2005
Statut
Membre
Dernière intervention
30 août 2012
24
Excuses pour la répétition, AlexN a ete plus rapide
Messages postés
492
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
12 janvier 2012
1
Non, ca ne vient pas de la.
Dans mon prog j'ai bien class et j'ai la meme erreur.
De plus une structure n'est jamais qu'une classe ou tout les membres sont publics.

En fait:
struct Foo
{
string f;
Foo();
~Foo();
void* affiche(void *p_data);
};

est absolument equivalent a:
class Foo
{
public :
string f;
Foo();
~Foo();
void* affiche(void *p_data);
};

Mais merci quand meme !

TuRn3r
Messages postés
694
Date d'inscription
lundi 5 décembre 2005
Statut
Membre
Dernière intervention
8 janvier 2014
15
Hum si les structures c'etaient stricto senso la même chose qu'une classe, personne les aurais inventé.

Ok syntaxiquement ça se ressemble. Mais les traitements et les propriétés d'une structure et d'une classe sont très très différents...Entre autres, ta fonction Foo() pour la structure est juste une fonction, tandis que pour la classe Foo c'est un constructeur.

En ce qui concerne les structure auto reférentes, il faut toujours faire préceder la définition de la structure par une declaration du type pointeur sur struct. Tu ne peux pas declarer la classe Foo, avant de l'avoir défini. Le compilateur ne connait pas la taille avant la definition. Il ne connait que la taille d'un pointeur.
Messages postés
492
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
12 janvier 2012
1
Admetons!
dans le cas suivant alors, d'ou peut provenir l'erreur svp ?
<hr size="2" width="100%">#include
#include

using namespace std;

static pthread_mutex_t mutex;

class Foo
{
public:
string f;
Foo();
~Foo();
void* affiche(void *p_data);
};

Foo::Foo ()
{
string tmp("Je suis Foo");
f=tmp;
}

Foo::~Foo()
{ }

void* Foo::affiche(void *p_data)
{
cout << f << endl;
return NULL;
}

int main()
{
pthread_mutex_init (&mutex, NULL);

pthread_t thrd1;

Foo f;

pthread_create(&thrd1,NULL,f.affiche,NULL);

pthread_join(thrd1, NULL);

cout << "Fin" << endl;

return 0;
}
<hr size="2" width="100%">
Pourquoi le compilo me dit-il : fichier.cpp:40: error: argument of type `void*(Foo::)(void*)' does not match `void*(*)(void*)'
Et comment résoudre mon problème.
D'avance merci !

TuRn3r
Messages postés
694
Date d'inscription
lundi 5 décembre 2005
Statut
Membre
Dernière intervention
8 janvier 2014
15
Ligne 40 c'est laquelle ?
vient du parametre de pthread_create() ? Le compilateur semble te dire qu'il attend un paramatère de type void*(*)(void*).
tentes un cast void*(*)(void*) sur le paramètre f.affiche()
Messages postés
492
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
12 janvier 2012
1
Non, je viens d'essayer, pas mieu.

La ligne 40, qui pose problème est celle-la:
pthread_create(&thrd1,NULL,f.affiche,NULL);

TuRn3r
Messages postés
694
Date d'inscription
lundi 5 décembre 2005
Statut
Membre
Dernière intervention
8 janvier 2014
15
Merci pour ces précisions

Bonne journée
Messages postés
492
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
12 janvier 2012
1
Idemement !

Merci à tous

TuRn3r
Messages postés
694
Date d'inscription
lundi 5 décembre 2005
Statut
Membre
Dernière intervention
8 janvier 2014
15
Juste un truc,

Je ne penses pas qu'une structure puisse être dérivée, ni que ses fonction membres puisse être surchargées ou virtualisées. Ni même que tous les mécanismes liés aux classes/objets (en dehors de la construction et destruction) pouvaient être applicables aux structures. Et j'ai quand même un doute.

Notemment je cite : Bjarne Stroustrup "Le langage C++" - Chapitre 5 - Les classes - 5.2.1-5.2.2 :

struct date {
int month, date, year;

void set (int, int, int);
void get (int *, int *, int *);
void next();
void print();
}

"La déclaration de date dans le paragraphe précédent offre un ensemble de fonctions pour la manipuler, mais elle ne précise pas que ces fonctions peuvent être les seules à pouvoir accéder aux objets de type date. Cette restriction peut être exprimée en utilisant une classe au lieu d'une struct : "

class date {
int month, date, year;

public:

void set (int, int, int);

void get (int *, int *, int *);

void next();

void print();

}

Le fait de distinguer struct et class par deux mots reservés implique que les mécanismes mis en jeu ne sont pas identiques. Sinon c'est de la redondance.

Je me trompe ?
Messages postés
492
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
12 janvier 2012
1
La différence se situ dans le fait que dans une struct tout est public et tu ne peux rien mettre en "private" ni "protected".
Alors que dans unje class par défaut tout est privé mais tu peux mettre des choses "public".

Or c'est bien ce qui est dit. Dans

class date {
int month, date, year;
public:
void set (int, int, int);
void get (int *, int *, int *);
void next();
void print();
}

month, date et year étant privé (par défaut) seule des fonctions membres de date pouront y avoir accès comme ici set, get, ....

Alors qu'avec la structure tu peux faire un:
date d;
d.month=11;

Alors qu'avec la class tu te feras jeté, il faudra que tu utilise le "setter" :
date d;
d.set(1,11,2006);

TuRn3r
Messages postés
20
Date d'inscription
vendredi 16 mai 2003
Statut
Membre
Dernière intervention
29 septembre 2006

[auteurdetail.aspx?ID= 304809 Voir http://c.developpez.com/faq/cpp/?page=classes et plus partuculièrement le paragraphe "]Quelle est la différence entre class et struct ?"





Je pensais que class = struct sans exception, en fait j'ai appris sur cette page qu'il y en avait une si on utilise template.



[auteurdetail.aspx?ID=304809 turnerom]-> Dans une structure les membres sont par défaut public mais rien empêche d'utiliser private ou protected. C'est en C pur que tout les membres sont forcément public mais dans ce cas en ne peut avoir que des membres de type variable, car le concept de fonction membre n'existe pas.

[auteurdetail.aspx?ID =638418 AlexN] -> Tu as écrit :"Le fait de distinguer struct et class par deux mots reservés implique
que les mécanismes mis en jeu ne sont pas identiques. Sinon c'est de la
redondance."
if et goto suffisent pour faire n'importe quel type de boucle pourtant for, while, do...while existent!
Messages postés
694
Date d'inscription
lundi 5 décembre 2005
Statut
Membre
Dernière intervention
8 janvier 2014
15
Ok,
J'ai effectivement mal lu, j'ai fait l'erreur de confondre struct c et struct c++.

Merci encore pour cette mise au point.