Julien IBARZ wrote in message
news:<4027f7b6$0$28274$...Le gros avantage est qu'une méthode statique est en tout point
similaire à une fonction (pointeurs, appels, etc).
Il est généralement nécessaire d'y avoir recours pour des
fonctionnalités encapsulées dans une classe mais nécessitant un
passage de pointeur sur fonction (pour un classe CThread par
exemple).
A moins que je n'ai pas compris votre propos, il est tout à fait
possible de faire des pointeurs vers des méthodes de classes non
statiques.
Oui, mais toutes les APIs de threading que je connais attendent comme
fonction principale d'un thread un pointeur vers une fonction "libre",
qui est nécessairement une fonction statique si on veut la mettre dans
une classe.
Julien IBARZ <ibarz.julien@free.fr> wrote in message
news:<4027f7b6$0$28274$636a15ce@news.free.fr>...
Le gros avantage est qu'une méthode statique est en tout point
similaire à une fonction (pointeurs, appels, etc).
Il est généralement nécessaire d'y avoir recours pour des
fonctionnalités encapsulées dans une classe mais nécessitant un
passage de pointeur sur fonction (pour un classe CThread par
exemple).
A moins que je n'ai pas compris votre propos, il est tout à fait
possible de faire des pointeurs vers des méthodes de classes non
statiques.
Oui, mais toutes les APIs de threading que je connais attendent comme
fonction principale d'un thread un pointeur vers une fonction "libre",
qui est nécessairement une fonction statique si on veut la mettre dans
une classe.
Julien IBARZ wrote in message
news:<4027f7b6$0$28274$...Le gros avantage est qu'une méthode statique est en tout point
similaire à une fonction (pointeurs, appels, etc).
Il est généralement nécessaire d'y avoir recours pour des
fonctionnalités encapsulées dans une classe mais nécessitant un
passage de pointeur sur fonction (pour un classe CThread par
exemple).
A moins que je n'ai pas compris votre propos, il est tout à fait
possible de faire des pointeurs vers des méthodes de classes non
statiques.
Oui, mais toutes les APIs de threading que je connais attendent comme
fonction principale d'un thread un pointeur vers une fonction "libre",
qui est nécessairement une fonction statique si on veut la mettre dans
une classe.
Sans connaître plus, c'est difficile à dire. Surtout, il faudrait savoir
la signature exacte de la fonction à passer en callback.
Si le callback a un paramètre, la meilleur solution est de s'en servir.
Comme on fait avec pthread_create:
[...]
Note que dans ce cas-ci, il faut absolument une fonction avec linkage
"C". Une fonction membre, static ou non, ne marche pas. (Selon la norme,
je ne crois pas que ça doit compiler. Mais dans la pratique, je ne
connais pas de compilateur qui signale l'erreur si la fonction est
statique. Ce qui donne un comportement indéfini, qui a parfois l'air
même de marcher.)
Je devrais utiliser le paramètre prévu par SDL pour tenir lieu de this
(mais c'est un void* !- ) ?
C'est normal dans une interface C. Alors, il y a static_cast.
Je fais de ma variable globale un membre statique ? (Ah mais non, j'ai
pas prévu d'en faire un pointeur...) Je change ma classe en namespace
? Autre chose ? Ou bien je garde ce que j'ai et j'arrête de poser des
questions bêtes ?-)
La variable globale est à éviter. Si l'interface permet un paramètre à
la fonction, sers-t'en. Sinon, j'aurais tendance à préférer une variable
statique membre, mais il n'y a pas de solution vraiment propre.
Sans connaître plus, c'est difficile à dire. Surtout, il faudrait savoir
la signature exacte de la fonction à passer en callback.
Si le callback a un paramètre, la meilleur solution est de s'en servir.
Comme on fait avec pthread_create:
[...]
Note que dans ce cas-ci, il faut absolument une fonction avec linkage
"C". Une fonction membre, static ou non, ne marche pas. (Selon la norme,
je ne crois pas que ça doit compiler. Mais dans la pratique, je ne
connais pas de compilateur qui signale l'erreur si la fonction est
statique. Ce qui donne un comportement indéfini, qui a parfois l'air
même de marcher.)
Je devrais utiliser le paramètre prévu par SDL pour tenir lieu de this
(mais c'est un void* !- ) ?
C'est normal dans une interface C. Alors, il y a static_cast.
Je fais de ma variable globale un membre statique ? (Ah mais non, j'ai
pas prévu d'en faire un pointeur...) Je change ma classe en namespace
? Autre chose ? Ou bien je garde ce que j'ai et j'arrête de poser des
questions bêtes ?-)
La variable globale est à éviter. Si l'interface permet un paramètre à
la fonction, sers-t'en. Sinon, j'aurais tendance à préférer une variable
statique membre, mais il n'y a pas de solution vraiment propre.
Sans connaître plus, c'est difficile à dire. Surtout, il faudrait savoir
la signature exacte de la fonction à passer en callback.
Si le callback a un paramètre, la meilleur solution est de s'en servir.
Comme on fait avec pthread_create:
[...]
Note que dans ce cas-ci, il faut absolument une fonction avec linkage
"C". Une fonction membre, static ou non, ne marche pas. (Selon la norme,
je ne crois pas que ça doit compiler. Mais dans la pratique, je ne
connais pas de compilateur qui signale l'erreur si la fonction est
statique. Ce qui donne un comportement indéfini, qui a parfois l'air
même de marcher.)
Je devrais utiliser le paramètre prévu par SDL pour tenir lieu de this
(mais c'est un void* !- ) ?
C'est normal dans une interface C. Alors, il y a static_cast.
Je fais de ma variable globale un membre statique ? (Ah mais non, j'ai
pas prévu d'en faire un pointeur...) Je change ma classe en namespace
? Autre chose ? Ou bien je garde ce que j'ai et j'arrête de poser des
questions bêtes ?-)
La variable globale est à éviter. Si l'interface permet un paramètre à
la fonction, sers-t'en. Sinon, j'aurais tendance à préférer une variable
statique membre, mais il n'y a pas de solution vraiment propre.
Si le callback a un paramètre, la meilleur solution est de s'en
servir. Comme on fait avec pthread_create:
[...]
Note que dans ce cas-ci, il faut absolument une fonction avec
linkage "C". Une fonction membre, static ou non, ne marche pas.
(Selon la norme, je ne crois pas que ça doit compiler. Mais dans la
pratique, je ne connais pas de compilateur qui signale l'erreur si
la fonction est statique. Ce qui donne un comportement indéfini, qui
a parfois l'air même de marcher.)
En effet, j'étais parti sur une fonction membre statique et ça avait
l'air de vachement bien marcher. Mais je ne comprends pas trop bien ce
qu'il y a de différent entre le type d'une fonction membre statique et
le type d'une fonction libre (je ne comprends pas non plus la
nécessité que celle-ci soit statique, d'ailleurs).
Je ne vois pas non plus la nécessité du linkage "C" ; tel que je me
figure la chose, extern "C" détermine la convention de nommage
employée.
Or, j'aurais dit qu'en utilisant des pointeurs, on se plaçait au-dela
de cette question...
Par contre, pour ce qui de l'assignation du callback, qui se fait par
simple affectation de pointeur, mon collègue, qui gère la portabilité
(de façon empirique), est d'avis de laisser un cast de toute façon. Il
me dit que selon les compilos, voire selon les versions, c'est des
choses plutôt sensibles. Y a du pour ? Du contre ?
Je devrais utiliser le paramètre prévu par SDL pour tenir lieu de
this (mais c'est un void* !- ) ?
C'est normal dans une interface C. Alors, il y a static_cast.
Oki. En fait, je voulais aussi voir si ça n'était pas une solution
jugée crado ;)
Je fais de ma variable globale un membre statique ? (Ah mais non,
j'ai pas prévu d'en faire un pointeur...) Je change ma classe en
namespace ? Autre chose ? Ou bien je garde ce que j'ai et j'arrête
de poser des questions bêtes ?-)
La variable globale est à éviter. Si l'interface permet un paramètre
à la fonction, sers-t'en. Sinon, j'aurais tendance à préférer une
variable statique membre, mais il n'y a pas de solution vraiment
propre.
Idem pour la donnée membre statique.
Si le callback a un paramètre, la meilleur solution est de s'en
servir. Comme on fait avec pthread_create:
[...]
Note que dans ce cas-ci, il faut absolument une fonction avec
linkage "C". Une fonction membre, static ou non, ne marche pas.
(Selon la norme, je ne crois pas que ça doit compiler. Mais dans la
pratique, je ne connais pas de compilateur qui signale l'erreur si
la fonction est statique. Ce qui donne un comportement indéfini, qui
a parfois l'air même de marcher.)
En effet, j'étais parti sur une fonction membre statique et ça avait
l'air de vachement bien marcher. Mais je ne comprends pas trop bien ce
qu'il y a de différent entre le type d'une fonction membre statique et
le type d'une fonction libre (je ne comprends pas non plus la
nécessité que celle-ci soit statique, d'ailleurs).
Je ne vois pas non plus la nécessité du linkage "C" ; tel que je me
figure la chose, extern "C" détermine la convention de nommage
employée.
Or, j'aurais dit qu'en utilisant des pointeurs, on se plaçait au-dela
de cette question...
Par contre, pour ce qui de l'assignation du callback, qui se fait par
simple affectation de pointeur, mon collègue, qui gère la portabilité
(de façon empirique), est d'avis de laisser un cast de toute façon. Il
me dit que selon les compilos, voire selon les versions, c'est des
choses plutôt sensibles. Y a du pour ? Du contre ?
Je devrais utiliser le paramètre prévu par SDL pour tenir lieu de
this (mais c'est un void* !- ) ?
C'est normal dans une interface C. Alors, il y a static_cast.
Oki. En fait, je voulais aussi voir si ça n'était pas une solution
jugée crado ;)
Je fais de ma variable globale un membre statique ? (Ah mais non,
j'ai pas prévu d'en faire un pointeur...) Je change ma classe en
namespace ? Autre chose ? Ou bien je garde ce que j'ai et j'arrête
de poser des questions bêtes ?-)
La variable globale est à éviter. Si l'interface permet un paramètre
à la fonction, sers-t'en. Sinon, j'aurais tendance à préférer une
variable statique membre, mais il n'y a pas de solution vraiment
propre.
Idem pour la donnée membre statique.
Si le callback a un paramètre, la meilleur solution est de s'en
servir. Comme on fait avec pthread_create:
[...]
Note que dans ce cas-ci, il faut absolument une fonction avec
linkage "C". Une fonction membre, static ou non, ne marche pas.
(Selon la norme, je ne crois pas que ça doit compiler. Mais dans la
pratique, je ne connais pas de compilateur qui signale l'erreur si
la fonction est statique. Ce qui donne un comportement indéfini, qui
a parfois l'air même de marcher.)
En effet, j'étais parti sur une fonction membre statique et ça avait
l'air de vachement bien marcher. Mais je ne comprends pas trop bien ce
qu'il y a de différent entre le type d'une fonction membre statique et
le type d'une fonction libre (je ne comprends pas non plus la
nécessité que celle-ci soit statique, d'ailleurs).
Je ne vois pas non plus la nécessité du linkage "C" ; tel que je me
figure la chose, extern "C" détermine la convention de nommage
employée.
Or, j'aurais dit qu'en utilisant des pointeurs, on se plaçait au-dela
de cette question...
Par contre, pour ce qui de l'assignation du callback, qui se fait par
simple affectation de pointeur, mon collègue, qui gère la portabilité
(de façon empirique), est d'avis de laisser un cast de toute façon. Il
me dit que selon les compilos, voire selon les versions, c'est des
choses plutôt sensibles. Y a du pour ? Du contre ?
Je devrais utiliser le paramètre prévu par SDL pour tenir lieu de
this (mais c'est un void* !- ) ?
C'est normal dans une interface C. Alors, il y a static_cast.
Oki. En fait, je voulais aussi voir si ça n'était pas une solution
jugée crado ;)
Je fais de ma variable globale un membre statique ? (Ah mais non,
j'ai pas prévu d'en faire un pointeur...) Je change ma classe en
namespace ? Autre chose ? Ou bien je garde ce que j'ai et j'arrête
de poser des questions bêtes ?-)
La variable globale est à éviter. Si l'interface permet un paramètre
à la fonction, sers-t'en. Sinon, j'aurais tendance à préférer une
variable statique membre, mais il n'y a pas de solution vraiment
propre.
Idem pour la donnée membre statique.
extern "C" static void* threadStarter( void* obj )
{
static_cast< Thread* >( obj )->run() ;
return NULL ;
}
La différence qui nous intéresse ici, c'est qu'on ne peut pas spécifier
un « linkage » pour une fonction membre statique -- il a forcement le
linkage par défaut, qui est C++. [...]
Si le langage permettait un « extern "C" » sur la fonction statique, je
suppose que ça marcherait, mais ce n'est pas le cas.
class Thread
{
public:
void start() ;
virtual void run() = 0 ;
private:
pthread_t myId ;
} ;
Je ne vois pas non plus la nécessité du linkage "C" ; tel que je me
figure la chose, extern "C" détermine la convention de nommage
employée.
Il détermine la convention de l'appel : le nommage, mais aussi où se
trouve les paramètres, ou on met l'adresse de rétour, ou on met une
valeur de rétour [...]
Par contre, pour ce qui de l'assignation du callback, qui se fait par
simple affectation de pointeur, mon collègue, qui gère la portabilité
(de façon empirique), est d'avis de laisser un cast de toute façon. Il
me dit que selon les compilos, voire selon les versions, c'est des
choses plutôt sensibles. Y a du pour ? Du contre ?
Je dirais qu'il ne faut absolument pas utiliser un cast. Il faut bien
passer une fonction du bon type, pour que ça marche partout, sans cast.
Le cast ne sert qu'à masquer les erreurs, pour qu'elles apparaissent à
l'execution, plutôt qu'à la compilation.
Oki. En fait, je voulais aussi voir si ça n'était pas une solution
jugée crado ;)
C'est crado dans la mésure que tout utilisation d'une interface C est
crado. Tu ne peux pas être plus pûr que l'API dont tu te sers. (Et si tu
crois que ça c'est crado, tu dois voir ce que je suis amené à faire pour
appeler readdir_r:-). Alors, là, c'est du crado. Mais l'interface est
normée par Posix, et je n'ai pas le droit de la modifier.)
La variable globale est à éviter. Si l'interface permet un paramètre
à la fonction, sers-t'en. Sinon, j'aurais tendance à préférer une
variable statique membre, mais il n'y a pas de solution vraiment
propre.
Idem pour la donnée membre statique.
Tout à fait. Les variables statiques ne cessent pas de poser des
problèmes en multi-thread.
extern "C" static void* threadStarter( void* obj )
{
static_cast< Thread* >( obj )->run() ;
return NULL ;
}
La différence qui nous intéresse ici, c'est qu'on ne peut pas spécifier
un « linkage » pour une fonction membre statique -- il a forcement le
linkage par défaut, qui est C++. [...]
Si le langage permettait un « extern "C" » sur la fonction statique, je
suppose que ça marcherait, mais ce n'est pas le cas.
class Thread
{
public:
void start() ;
virtual void run() = 0 ;
private:
pthread_t myId ;
} ;
Je ne vois pas non plus la nécessité du linkage "C" ; tel que je me
figure la chose, extern "C" détermine la convention de nommage
employée.
Il détermine la convention de l'appel : le nommage, mais aussi où se
trouve les paramètres, ou on met l'adresse de rétour, ou on met une
valeur de rétour [...]
Par contre, pour ce qui de l'assignation du callback, qui se fait par
simple affectation de pointeur, mon collègue, qui gère la portabilité
(de façon empirique), est d'avis de laisser un cast de toute façon. Il
me dit que selon les compilos, voire selon les versions, c'est des
choses plutôt sensibles. Y a du pour ? Du contre ?
Je dirais qu'il ne faut absolument pas utiliser un cast. Il faut bien
passer une fonction du bon type, pour que ça marche partout, sans cast.
Le cast ne sert qu'à masquer les erreurs, pour qu'elles apparaissent à
l'execution, plutôt qu'à la compilation.
Oki. En fait, je voulais aussi voir si ça n'était pas une solution
jugée crado ;)
C'est crado dans la mésure que tout utilisation d'une interface C est
crado. Tu ne peux pas être plus pûr que l'API dont tu te sers. (Et si tu
crois que ça c'est crado, tu dois voir ce que je suis amené à faire pour
appeler readdir_r:-). Alors, là, c'est du crado. Mais l'interface est
normée par Posix, et je n'ai pas le droit de la modifier.)
La variable globale est à éviter. Si l'interface permet un paramètre
à la fonction, sers-t'en. Sinon, j'aurais tendance à préférer une
variable statique membre, mais il n'y a pas de solution vraiment
propre.
Idem pour la donnée membre statique.
Tout à fait. Les variables statiques ne cessent pas de poser des
problèmes en multi-thread.
extern "C" static void* threadStarter( void* obj )
{
static_cast< Thread* >( obj )->run() ;
return NULL ;
}
La différence qui nous intéresse ici, c'est qu'on ne peut pas spécifier
un « linkage » pour une fonction membre statique -- il a forcement le
linkage par défaut, qui est C++. [...]
Si le langage permettait un « extern "C" » sur la fonction statique, je
suppose que ça marcherait, mais ce n'est pas le cas.
class Thread
{
public:
void start() ;
virtual void run() = 0 ;
private:
pthread_t myId ;
} ;
Je ne vois pas non plus la nécessité du linkage "C" ; tel que je me
figure la chose, extern "C" détermine la convention de nommage
employée.
Il détermine la convention de l'appel : le nommage, mais aussi où se
trouve les paramètres, ou on met l'adresse de rétour, ou on met une
valeur de rétour [...]
Par contre, pour ce qui de l'assignation du callback, qui se fait par
simple affectation de pointeur, mon collègue, qui gère la portabilité
(de façon empirique), est d'avis de laisser un cast de toute façon. Il
me dit que selon les compilos, voire selon les versions, c'est des
choses plutôt sensibles. Y a du pour ? Du contre ?
Je dirais qu'il ne faut absolument pas utiliser un cast. Il faut bien
passer une fonction du bon type, pour que ça marche partout, sans cast.
Le cast ne sert qu'à masquer les erreurs, pour qu'elles apparaissent à
l'execution, plutôt qu'à la compilation.
Oki. En fait, je voulais aussi voir si ça n'était pas une solution
jugée crado ;)
C'est crado dans la mésure que tout utilisation d'une interface C est
crado. Tu ne peux pas être plus pûr que l'API dont tu te sers. (Et si tu
crois que ça c'est crado, tu dois voir ce que je suis amené à faire pour
appeler readdir_r:-). Alors, là, c'est du crado. Mais l'interface est
normée par Posix, et je n'ai pas le droit de la modifier.)
La variable globale est à éviter. Si l'interface permet un paramètre
à la fonction, sers-t'en. Sinon, j'aurais tendance à préférer une
variable statique membre, mais il n'y a pas de solution vraiment
propre.
Idem pour la donnée membre statique.
Tout à fait. Les variables statiques ne cessent pas de poser des
problèmes en multi-thread.
peut-on faire confiance à this dans le corps du constructeur ? (Ou bien
suis-je en train de m'emmêler les pinceaux avec mes vieux souvenirs de
java ?-)
J'ai deux idées là-dessus :
1) passé la liste d'init (l'{ de la définition du ctor, plus
exactement), ça devrait aller ;
2) je vais essayer de vérifier ça tout de suite, mais je ne suis pas
certain de le trouver rapidement (donc je laisse quand même la question ;).
peut-on faire confiance à this dans le corps du constructeur ? (Ou bien
suis-je en train de m'emmêler les pinceaux avec mes vieux souvenirs de
java ?-)
J'ai deux idées là-dessus :
1) passé la liste d'init (l'{ de la définition du ctor, plus
exactement), ça devrait aller ;
2) je vais essayer de vérifier ça tout de suite, mais je ne suis pas
certain de le trouver rapidement (donc je laisse quand même la question ;).
peut-on faire confiance à this dans le corps du constructeur ? (Ou bien
suis-je en train de m'emmêler les pinceaux avec mes vieux souvenirs de
java ?-)
J'ai deux idées là-dessus :
1) passé la liste d'init (l'{ de la définition du ctor, plus
exactement), ça devrait aller ;
2) je vais essayer de vérifier ça tout de suite, mais je ne suis pas
certain de le trouver rapidement (donc je laisse quand même la question ;).
Ca râle sur :
extern "C" static /* fonc */
En effet. Je ne connais pas les règles exactes, mais c'est possible
qu'une fonction « extern "C" » ne peut pas être statique.
(C'est aussi possible qu'il y a une erreur dans le compilateur, qui
traite l'extern ici comme un vrai externe, c-à-d le contraire de
static.)Ca passe mieux avec :
extern "C" { static /* fonc */ }
Alors, tu as déjà trouvé la solution pour ton compilateur. Dans
la doute, on pourrait ôter le static complétement.
La différence qui nous intéresse ici, c'est qu'on ne peut
pas spécifier un « linkage » pour une fonction membre
statique -- il a forcement le linkage par défaut, qui est C++.
Est-ce que j'aurais tort d'étendre en «le langage ne permet
pas de 'extern "C"', pour n'importe quel type de déclaration de
fonction à l'intérieur d'une classe» ?
En effet. Mais il ne m'étais pas venu à l'ésprit qu'on pouvait
vouloir une fonction member non statique avec linkage "C".
Dans mon cas, donc, la fonction membre équivalente à
threadStarter() est appelée par «le système» d'une
façon sur laquelle je n'ai aucun contrôle (on dit asynchrone,
je crois ?).
C'est en fait aussi le cas de la fonction de démarrage du thread.
donc parti sur l'idée d'avoir run() en private. Or, à ce
moment, il me faudrait déclarer threadStarter() en friend de
Thread, ce qui, avec son extern "C", n'a pas l'air envisageable du
tout.
Je crois que si :
extern "C" void* threadStarter( void* p )
{
static_cast< Thread*>( p )->run() ;
return NULL ;
}
class Thread
{
friend void* threadStarter( void* ) ;
// ...
} ;
A priori, je crois que ça doit marcher.
Du coup, pour l'instant, mon run() se retrouve en public avec des
raisons de ne pas l'être...
Bof. Si c'est le seul problème...
C'est crado dans la mésure que tout utilisation d'une interface
C est crado. Tu ne peux pas être plus pûr que l'API dont tu
te sers. (Et si tu crois que ça c'est crado, tu dois voir ce
que je suis amené à faire pour appeler readdir_r:-). Alors,
là, c'est du crado. Mais l'interface est normée par Posix,
et je n'ai pas le droit de la modifier.)
Hmm... j'aurais bien demandé à voir par simple masochisme,
mais tout compte fait, le proto ne me parle absolument pas ;)
Le proto, ce n'est pas le tout. Il y a un paramètre dirent*. Mais
quand on en lit la description, et qu'on régarde dans l'en-tête,
il se trouve que dirent, c'est :
struct dirent
{
// ...
char d_name[ 1 ] ;
} ;
et que la description de la fonction exige qu'en fait, il y a assez de
place derrière pour mettre le nom.
En fait, ce qu'ils veulent, c'est :
struct dirent
{
// ...
char d_name[] ;
} ;
Seulement, ce n'était pas légal quand ils ont formulé leur
norme (et ce n'est toujours pas légal en C++). Alors, il se sont
servi d'un ancien hack, illégal selon la norme C, mais qui fonctionne
à peu près partout, c-à-d qu'il s'attend à ce qu'on fasse :
dirent* p = (dirent*)malloc( sizeof( dirent ) + N ) ;
Ca râle sur :
extern "C" static /* fonc */
En effet. Je ne connais pas les règles exactes, mais c'est possible
qu'une fonction « extern "C" » ne peut pas être statique.
(C'est aussi possible qu'il y a une erreur dans le compilateur, qui
traite l'extern ici comme un vrai externe, c-à-d le contraire de
static.)
Ca passe mieux avec :
extern "C" { static /* fonc */ }
Alors, tu as déjà trouvé la solution pour ton compilateur. Dans
la doute, on pourrait ôter le static complétement.
La différence qui nous intéresse ici, c'est qu'on ne peut
pas spécifier un « linkage » pour une fonction membre
statique -- il a forcement le linkage par défaut, qui est C++.
Est-ce que j'aurais tort d'étendre en «le langage ne permet
pas de 'extern "C"', pour n'importe quel type de déclaration de
fonction à l'intérieur d'une classe» ?
En effet. Mais il ne m'étais pas venu à l'ésprit qu'on pouvait
vouloir une fonction member non statique avec linkage "C".
Dans mon cas, donc, la fonction membre équivalente à
threadStarter() est appelée par «le système» d'une
façon sur laquelle je n'ai aucun contrôle (on dit asynchrone,
je crois ?).
C'est en fait aussi le cas de la fonction de démarrage du thread.
donc parti sur l'idée d'avoir run() en private. Or, à ce
moment, il me faudrait déclarer threadStarter() en friend de
Thread, ce qui, avec son extern "C", n'a pas l'air envisageable du
tout.
Je crois que si :
extern "C" void* threadStarter( void* p )
{
static_cast< Thread*>( p )->run() ;
return NULL ;
}
class Thread
{
friend void* threadStarter( void* ) ;
// ...
} ;
A priori, je crois que ça doit marcher.
Du coup, pour l'instant, mon run() se retrouve en public avec des
raisons de ne pas l'être...
Bof. Si c'est le seul problème...
C'est crado dans la mésure que tout utilisation d'une interface
C est crado. Tu ne peux pas être plus pûr que l'API dont tu
te sers. (Et si tu crois que ça c'est crado, tu dois voir ce
que je suis amené à faire pour appeler readdir_r:-). Alors,
là, c'est du crado. Mais l'interface est normée par Posix,
et je n'ai pas le droit de la modifier.)
Hmm... j'aurais bien demandé à voir par simple masochisme,
mais tout compte fait, le proto ne me parle absolument pas ;)
Le proto, ce n'est pas le tout. Il y a un paramètre dirent*. Mais
quand on en lit la description, et qu'on régarde dans l'en-tête,
il se trouve que dirent, c'est :
struct dirent
{
// ...
char d_name[ 1 ] ;
} ;
et que la description de la fonction exige qu'en fait, il y a assez de
place derrière pour mettre le nom.
En fait, ce qu'ils veulent, c'est :
struct dirent
{
// ...
char d_name[] ;
} ;
Seulement, ce n'était pas légal quand ils ont formulé leur
norme (et ce n'est toujours pas légal en C++). Alors, il se sont
servi d'un ancien hack, illégal selon la norme C, mais qui fonctionne
à peu près partout, c-à-d qu'il s'attend à ce qu'on fasse :
dirent* p = (dirent*)malloc( sizeof( dirent ) + N ) ;
Ca râle sur :
extern "C" static /* fonc */
En effet. Je ne connais pas les règles exactes, mais c'est possible
qu'une fonction « extern "C" » ne peut pas être statique.
(C'est aussi possible qu'il y a une erreur dans le compilateur, qui
traite l'extern ici comme un vrai externe, c-à-d le contraire de
static.)Ca passe mieux avec :
extern "C" { static /* fonc */ }
Alors, tu as déjà trouvé la solution pour ton compilateur. Dans
la doute, on pourrait ôter le static complétement.
La différence qui nous intéresse ici, c'est qu'on ne peut
pas spécifier un « linkage » pour une fonction membre
statique -- il a forcement le linkage par défaut, qui est C++.
Est-ce que j'aurais tort d'étendre en «le langage ne permet
pas de 'extern "C"', pour n'importe quel type de déclaration de
fonction à l'intérieur d'une classe» ?
En effet. Mais il ne m'étais pas venu à l'ésprit qu'on pouvait
vouloir une fonction member non statique avec linkage "C".
Dans mon cas, donc, la fonction membre équivalente à
threadStarter() est appelée par «le système» d'une
façon sur laquelle je n'ai aucun contrôle (on dit asynchrone,
je crois ?).
C'est en fait aussi le cas de la fonction de démarrage du thread.
donc parti sur l'idée d'avoir run() en private. Or, à ce
moment, il me faudrait déclarer threadStarter() en friend de
Thread, ce qui, avec son extern "C", n'a pas l'air envisageable du
tout.
Je crois que si :
extern "C" void* threadStarter( void* p )
{
static_cast< Thread*>( p )->run() ;
return NULL ;
}
class Thread
{
friend void* threadStarter( void* ) ;
// ...
} ;
A priori, je crois que ça doit marcher.
Du coup, pour l'instant, mon run() se retrouve en public avec des
raisons de ne pas l'être...
Bof. Si c'est le seul problème...
C'est crado dans la mésure que tout utilisation d'une interface
C est crado. Tu ne peux pas être plus pûr que l'API dont tu
te sers. (Et si tu crois que ça c'est crado, tu dois voir ce
que je suis amené à faire pour appeler readdir_r:-). Alors,
là, c'est du crado. Mais l'interface est normée par Posix,
et je n'ai pas le droit de la modifier.)
Hmm... j'aurais bien demandé à voir par simple masochisme,
mais tout compte fait, le proto ne me parle absolument pas ;)
Le proto, ce n'est pas le tout. Il y a un paramètre dirent*. Mais
quand on en lit la description, et qu'on régarde dans l'en-tête,
il se trouve que dirent, c'est :
struct dirent
{
// ...
char d_name[ 1 ] ;
} ;
et que la description de la fonction exige qu'en fait, il y a assez de
place derrière pour mettre le nom.
En fait, ce qu'ils veulent, c'est :
struct dirent
{
// ...
char d_name[] ;
} ;
Seulement, ce n'était pas légal quand ils ont formulé leur
norme (et ce n'est toujours pas légal en C++). Alors, il se sont
servi d'un ancien hack, illégal selon la norme C, mais qui fonctionne
à peu près partout, c-à-d qu'il s'attend à ce qu'on fasse :
dirent* p = (dirent*)malloc( sizeof( dirent ) + N ) ;
Ca râle sur :
extern "C" static /* fonc */
En effet. Je ne connais pas les règles exactes, mais c'est possible
qu'une fonction « extern "C" » ne peut pas être statique. (C'est
aussi possible qu'il y a une erreur dans le compilateur, qui traite
l'extern ici comme un vrai externe, c-à-d le contraire de static.)Ca passe mieux avec :
extern "C" { static /* fonc */ }
Alors, tu as déjà trouvé la solution pour ton compilateur. Dans la
doute, on pourrait ôter le static complétement.
(Je m'étonne un peu qu'un plus chevelu que moi n'ait pas encore
relevé..)
En fait, la soluce en question est inspirée d'un passage du TC++L, que
je vais essayer de retrouver pour le coup... dans §9.2.4 :
« Any declaration can appear within a linkage block :
extern "C" { // any declaration here, for example:
int g1; // definition
extern int g2; // declaration, not definition
}
In particular, the scope and storage class of variables are not
affected, so g1 is still a global variable --- and is still defined
rather than just declared. To declare but not define variable, you must
apply the keyword extern directly in the declaration. For example :
extern "C" int g3; // declaration, not definition
This looks odd at first glance. However, it is a simple consequence of
keeping the meaning unchanged when adding "C" to an extern declaration
and the meaning of a file unchanged when enclosing it in a linkage
block. »
Et comme mon édition n'est plus trop récente (enfin, selon mes
critères, toujours ;-P ), on va aussi vérifier dans mon nouveau
bouquin.
...
Ce fut un peu plus dur, mais §7.5/7 dit à peu près la même chose (en
un peu moins clair bien sûr ;)La différence qui nous intéresse ici, c'est qu'on ne peut pas
spécifier un « linkage » pour une fonction membre statique -- il
a forcement le linkage par défaut, qui est C++.
Est-ce que j'aurais tort d'étendre en «le langage ne permet pas de
'extern "C"', pour n'importe quel type de déclaration de fonction
à l'intérieur d'une classe» ?
En effet. Mais il ne m'étais pas venu à l'ésprit qu'on pouvait
vouloir une fonction member non statique avec linkage "C".
En fait, je n'étais pas allé jusqu'à vraiment creuser non plus ce
point là. Le cas qui m'intéressait surtout, c'était friend. Comme je
crois me souvenir qu'il est un peu bancal d'assimiler friend et
déclaration, j'ai préféré extrapoler un peu plus large ;)Dans mon cas, donc, la fonction membre équivalente à
threadStarter() est appelée par «le système» d'une façon sur
laquelle je n'ai aucun contrôle (on dit asynchrone, je crois ?).
C'est en fait aussi le cas de la fonction de démarrage du thread.
La différence que je faisais, c'est qu'on déclenche quand même l'appel
à threadStarter() en passant explicitement par Thread::start(). Dans
mon cas, SDL prend le pointeur de fonction et s'en sert quand elle en
a besoin (pour remplir son buffer de son, en l'occurence).
Etant donné que je ne suis pas resté penché sur le problème plus
longtemps que ça, je ne suis plus trop certain de voir en quoi ça
ferait une grosse différence.
donc parti sur l'idée d'avoir run() en private. Or, à ce moment,
il me faudrait déclarer threadStarter() en friend de Thread, ce
qui, avec son extern "C", n'a pas l'air envisageable du tout.
Je crois que si :
extern "C" void* threadStarter( void* p )
{
static_cast< Thread*>( p )->run() ;
return NULL ;
}
class Thread
{
friend void* threadStarter( void* ) ;
// ...
} ;
A priori, je crois que ça doit marcher.
Ou bien quelque chose comme :
class Thread {
extern "C" { friend void* threadStarter (void*); }
};
... on voit des exemples de ce genre de choses qui font un peur, dans
la norme ;)
Du coup, pour l'instant, mon run() se retrouve en public avec des
raisons de ne pas l'être...
Bof. Si c'est le seul problème...
Oui, chose incroyable venant de moi, j'ai préféré la solution qui
marche bien à la recherche acharnée d'une solution à un ennui mineur
de conception !
C'est crado dans la mésure que tout utilisation d'une interface
C est crado. Tu ne peux pas être plus pûr que l'API dont tu te
sers. (Et si tu crois que ça c'est crado, tu dois voir ce que je
suis amené à faire pour appeler readdir_r:-). Alors, là, c'est
du crado. Mais l'interface est normée par Posix, et je n'ai pas
le droit de la modifier.)
Hmm... j'aurais bien demandé à voir par simple masochisme, mais
tout compte fait, le proto ne me parle absolument pas ;)
Le proto, ce n'est pas le tout. Il y a un paramètre dirent*. Mais
quand on en lit la description, et qu'on régarde dans l'en-tête, il
se trouve que dirent, c'est :
struct dirent
{
// ...
char d_name[ 1 ] ;
} ;
et que la description de la fonction exige qu'en fait, il y a assez
de place derrière pour mettre le nom.
En fait, ce qu'ils veulent, c'est :
struct dirent
{
// ...
char d_name[] ;
} ;
Seulement, ce n'était pas légal quand ils ont formulé leur norme (et
ce n'est toujours pas légal en C++). Alors, il se sont servi d'un
ancien hack, illégal selon la norme C, mais qui fonctionne à peu
près partout, c-à-d qu'il s'attend à ce qu'on fasse :
dirent* p = (dirent*)malloc( sizeof( dirent ) + N ) ;
Oui, je me souviens de ce truc, on m'avait montré ça «à l'école» ;)
Effectivement, c'est un peu goret, mais je ne savais pas que c'était
illégal.
Et, si je peux demander, tu fais comment ? Tu continues à faire comme
ça, ou tu as une astuce avec new ?-)
Ca râle sur :
extern "C" static /* fonc */
En effet. Je ne connais pas les règles exactes, mais c'est possible
qu'une fonction « extern "C" » ne peut pas être statique. (C'est
aussi possible qu'il y a une erreur dans le compilateur, qui traite
l'extern ici comme un vrai externe, c-à-d le contraire de static.)
Ca passe mieux avec :
extern "C" { static /* fonc */ }
Alors, tu as déjà trouvé la solution pour ton compilateur. Dans la
doute, on pourrait ôter le static complétement.
(Je m'étonne un peu qu'un plus chevelu que moi n'ait pas encore
relevé..)
En fait, la soluce en question est inspirée d'un passage du TC++L, que
je vais essayer de retrouver pour le coup... dans §9.2.4 :
« Any declaration can appear within a linkage block :
extern "C" { // any declaration here, for example:
int g1; // definition
extern int g2; // declaration, not definition
}
In particular, the scope and storage class of variables are not
affected, so g1 is still a global variable --- and is still defined
rather than just declared. To declare but not define variable, you must
apply the keyword extern directly in the declaration. For example :
extern "C" int g3; // declaration, not definition
This looks odd at first glance. However, it is a simple consequence of
keeping the meaning unchanged when adding "C" to an extern declaration
and the meaning of a file unchanged when enclosing it in a linkage
block. »
Et comme mon édition n'est plus trop récente (enfin, selon mes
critères, toujours ;-P ), on va aussi vérifier dans mon nouveau
bouquin.
...
Ce fut un peu plus dur, mais §7.5/7 dit à peu près la même chose (en
un peu moins clair bien sûr ;)
La différence qui nous intéresse ici, c'est qu'on ne peut pas
spécifier un « linkage » pour une fonction membre statique -- il
a forcement le linkage par défaut, qui est C++.
Est-ce que j'aurais tort d'étendre en «le langage ne permet pas de
'extern "C"', pour n'importe quel type de déclaration de fonction
à l'intérieur d'une classe» ?
En effet. Mais il ne m'étais pas venu à l'ésprit qu'on pouvait
vouloir une fonction member non statique avec linkage "C".
En fait, je n'étais pas allé jusqu'à vraiment creuser non plus ce
point là. Le cas qui m'intéressait surtout, c'était friend. Comme je
crois me souvenir qu'il est un peu bancal d'assimiler friend et
déclaration, j'ai préféré extrapoler un peu plus large ;)
Dans mon cas, donc, la fonction membre équivalente à
threadStarter() est appelée par «le système» d'une façon sur
laquelle je n'ai aucun contrôle (on dit asynchrone, je crois ?).
C'est en fait aussi le cas de la fonction de démarrage du thread.
La différence que je faisais, c'est qu'on déclenche quand même l'appel
à threadStarter() en passant explicitement par Thread::start(). Dans
mon cas, SDL prend le pointeur de fonction et s'en sert quand elle en
a besoin (pour remplir son buffer de son, en l'occurence).
Etant donné que je ne suis pas resté penché sur le problème plus
longtemps que ça, je ne suis plus trop certain de voir en quoi ça
ferait une grosse différence.
donc parti sur l'idée d'avoir run() en private. Or, à ce moment,
il me faudrait déclarer threadStarter() en friend de Thread, ce
qui, avec son extern "C", n'a pas l'air envisageable du tout.
Je crois que si :
extern "C" void* threadStarter( void* p )
{
static_cast< Thread*>( p )->run() ;
return NULL ;
}
class Thread
{
friend void* threadStarter( void* ) ;
// ...
} ;
A priori, je crois que ça doit marcher.
Ou bien quelque chose comme :
class Thread {
extern "C" { friend void* threadStarter (void*); }
};
... on voit des exemples de ce genre de choses qui font un peur, dans
la norme ;)
Du coup, pour l'instant, mon run() se retrouve en public avec des
raisons de ne pas l'être...
Bof. Si c'est le seul problème...
Oui, chose incroyable venant de moi, j'ai préféré la solution qui
marche bien à la recherche acharnée d'une solution à un ennui mineur
de conception !
C'est crado dans la mésure que tout utilisation d'une interface
C est crado. Tu ne peux pas être plus pûr que l'API dont tu te
sers. (Et si tu crois que ça c'est crado, tu dois voir ce que je
suis amené à faire pour appeler readdir_r:-). Alors, là, c'est
du crado. Mais l'interface est normée par Posix, et je n'ai pas
le droit de la modifier.)
Hmm... j'aurais bien demandé à voir par simple masochisme, mais
tout compte fait, le proto ne me parle absolument pas ;)
Le proto, ce n'est pas le tout. Il y a un paramètre dirent*. Mais
quand on en lit la description, et qu'on régarde dans l'en-tête, il
se trouve que dirent, c'est :
struct dirent
{
// ...
char d_name[ 1 ] ;
} ;
et que la description de la fonction exige qu'en fait, il y a assez
de place derrière pour mettre le nom.
En fait, ce qu'ils veulent, c'est :
struct dirent
{
// ...
char d_name[] ;
} ;
Seulement, ce n'était pas légal quand ils ont formulé leur norme (et
ce n'est toujours pas légal en C++). Alors, il se sont servi d'un
ancien hack, illégal selon la norme C, mais qui fonctionne à peu
près partout, c-à-d qu'il s'attend à ce qu'on fasse :
dirent* p = (dirent*)malloc( sizeof( dirent ) + N ) ;
Oui, je me souviens de ce truc, on m'avait montré ça «à l'école» ;)
Effectivement, c'est un peu goret, mais je ne savais pas que c'était
illégal.
Et, si je peux demander, tu fais comment ? Tu continues à faire comme
ça, ou tu as une astuce avec new ?-)
Ca râle sur :
extern "C" static /* fonc */
En effet. Je ne connais pas les règles exactes, mais c'est possible
qu'une fonction « extern "C" » ne peut pas être statique. (C'est
aussi possible qu'il y a une erreur dans le compilateur, qui traite
l'extern ici comme un vrai externe, c-à-d le contraire de static.)Ca passe mieux avec :
extern "C" { static /* fonc */ }
Alors, tu as déjà trouvé la solution pour ton compilateur. Dans la
doute, on pourrait ôter le static complétement.
(Je m'étonne un peu qu'un plus chevelu que moi n'ait pas encore
relevé..)
En fait, la soluce en question est inspirée d'un passage du TC++L, que
je vais essayer de retrouver pour le coup... dans §9.2.4 :
« Any declaration can appear within a linkage block :
extern "C" { // any declaration here, for example:
int g1; // definition
extern int g2; // declaration, not definition
}
In particular, the scope and storage class of variables are not
affected, so g1 is still a global variable --- and is still defined
rather than just declared. To declare but not define variable, you must
apply the keyword extern directly in the declaration. For example :
extern "C" int g3; // declaration, not definition
This looks odd at first glance. However, it is a simple consequence of
keeping the meaning unchanged when adding "C" to an extern declaration
and the meaning of a file unchanged when enclosing it in a linkage
block. »
Et comme mon édition n'est plus trop récente (enfin, selon mes
critères, toujours ;-P ), on va aussi vérifier dans mon nouveau
bouquin.
...
Ce fut un peu plus dur, mais §7.5/7 dit à peu près la même chose (en
un peu moins clair bien sûr ;)La différence qui nous intéresse ici, c'est qu'on ne peut pas
spécifier un « linkage » pour une fonction membre statique -- il
a forcement le linkage par défaut, qui est C++.
Est-ce que j'aurais tort d'étendre en «le langage ne permet pas de
'extern "C"', pour n'importe quel type de déclaration de fonction
à l'intérieur d'une classe» ?
En effet. Mais il ne m'étais pas venu à l'ésprit qu'on pouvait
vouloir une fonction member non statique avec linkage "C".
En fait, je n'étais pas allé jusqu'à vraiment creuser non plus ce
point là. Le cas qui m'intéressait surtout, c'était friend. Comme je
crois me souvenir qu'il est un peu bancal d'assimiler friend et
déclaration, j'ai préféré extrapoler un peu plus large ;)Dans mon cas, donc, la fonction membre équivalente à
threadStarter() est appelée par «le système» d'une façon sur
laquelle je n'ai aucun contrôle (on dit asynchrone, je crois ?).
C'est en fait aussi le cas de la fonction de démarrage du thread.
La différence que je faisais, c'est qu'on déclenche quand même l'appel
à threadStarter() en passant explicitement par Thread::start(). Dans
mon cas, SDL prend le pointeur de fonction et s'en sert quand elle en
a besoin (pour remplir son buffer de son, en l'occurence).
Etant donné que je ne suis pas resté penché sur le problème plus
longtemps que ça, je ne suis plus trop certain de voir en quoi ça
ferait une grosse différence.
donc parti sur l'idée d'avoir run() en private. Or, à ce moment,
il me faudrait déclarer threadStarter() en friend de Thread, ce
qui, avec son extern "C", n'a pas l'air envisageable du tout.
Je crois que si :
extern "C" void* threadStarter( void* p )
{
static_cast< Thread*>( p )->run() ;
return NULL ;
}
class Thread
{
friend void* threadStarter( void* ) ;
// ...
} ;
A priori, je crois que ça doit marcher.
Ou bien quelque chose comme :
class Thread {
extern "C" { friend void* threadStarter (void*); }
};
... on voit des exemples de ce genre de choses qui font un peur, dans
la norme ;)
Du coup, pour l'instant, mon run() se retrouve en public avec des
raisons de ne pas l'être...
Bof. Si c'est le seul problème...
Oui, chose incroyable venant de moi, j'ai préféré la solution qui
marche bien à la recherche acharnée d'une solution à un ennui mineur
de conception !
C'est crado dans la mésure que tout utilisation d'une interface
C est crado. Tu ne peux pas être plus pûr que l'API dont tu te
sers. (Et si tu crois que ça c'est crado, tu dois voir ce que je
suis amené à faire pour appeler readdir_r:-). Alors, là, c'est
du crado. Mais l'interface est normée par Posix, et je n'ai pas
le droit de la modifier.)
Hmm... j'aurais bien demandé à voir par simple masochisme, mais
tout compte fait, le proto ne me parle absolument pas ;)
Le proto, ce n'est pas le tout. Il y a un paramètre dirent*. Mais
quand on en lit la description, et qu'on régarde dans l'en-tête, il
se trouve que dirent, c'est :
struct dirent
{
// ...
char d_name[ 1 ] ;
} ;
et que la description de la fonction exige qu'en fait, il y a assez
de place derrière pour mettre le nom.
En fait, ce qu'ils veulent, c'est :
struct dirent
{
// ...
char d_name[] ;
} ;
Seulement, ce n'était pas légal quand ils ont formulé leur norme (et
ce n'est toujours pas légal en C++). Alors, il se sont servi d'un
ancien hack, illégal selon la norme C, mais qui fonctionne à peu
près partout, c-à-d qu'il s'attend à ce qu'on fasse :
dirent* p = (dirent*)malloc( sizeof( dirent ) + N ) ;
Oui, je me souviens de ce truc, on m'avait montré ça «à l'école» ;)
Effectivement, c'est un peu goret, mais je ne savais pas que c'était
illégal.
Et, si je peux demander, tu fais comment ? Tu continues à faire comme
ça, ou tu as une astuce avec new ?-)
Anubis wrote in message
news:<c08k47$siq$...James Kanze wrote:Nicolas Aunai writes:je comprends l'intéret d'une variable static dans une classe,
mais pas celui d'une méthode static... que sont-elles et à quoi
servent-elles ?Elles sont des fonctions membres auxquelles on ne passe pas de
pointeur this.Le fait qu'elles n'aient pas le pointeur this par défaut en fait
surtout des fonctions (et non pas des méthodes) qui sont simplement
encapsulées dans la classe comme des fonctions le seraient dans un
namespace.
Elles ont bien accès à la partie privée de la classe. Elles font partie
integrale de l'interface de la classe.Le gros avantage est qu'une méthode statique est en tout point
similaire à une fonction (pointeurs, appels, etc).
Le gros avantage, par rapport à une fonction non-membre, c'est qu'elle a
accès à la partie privée de la classe. Le gros avantage, par rapport à
une fonction membre non-statique, c'est qu'elle peut être appelée sans
instance de la classe.Il est généralement nécessaire d'y avoir recours pour des
fonctionnalités encapsulées dans une classe mais nécessitant un
passage de pointeur sur fonction (pour un classe CThread par exemple).
C'est en effet une des utilisations importantes, mais pas la seule. Je
dirais que la vaste majorité de mes fonctions statiques sont ou bien des
fonctions usine d'une sorte ou une autre, y comprise l'instance() du
singleton, ou bien des fonctions de « prétraitement » des paramètres
d'un constructeur. J'ai aussi un ou deux cas particuliers, qui me
servent dans une RTTI portable fait maison. Et une fois, évidemment, la
fonction que je passe à pthread_create. (Mais je fais des serveurs, sans
GUI. Je crois que dans les GUI, il y a beaucoup plus de callback.)
--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
Anubis <anubis@remove-anti-spam-tags.genezys.net> wrote in message
news:<c08k47$siq$1@aphrodite.grec.isp.9tel.net>...
James Kanze wrote:
Nicolas Aunai <nicolas.aunai@free.fr> writes:
je comprends l'intéret d'une variable static dans une classe,
mais pas celui d'une méthode static... que sont-elles et à quoi
servent-elles ?
Elles sont des fonctions membres auxquelles on ne passe pas de
pointeur this.
Le fait qu'elles n'aient pas le pointeur this par défaut en fait
surtout des fonctions (et non pas des méthodes) qui sont simplement
encapsulées dans la classe comme des fonctions le seraient dans un
namespace.
Elles ont bien accès à la partie privée de la classe. Elles font partie
integrale de l'interface de la classe.
Le gros avantage est qu'une méthode statique est en tout point
similaire à une fonction (pointeurs, appels, etc).
Le gros avantage, par rapport à une fonction non-membre, c'est qu'elle a
accès à la partie privée de la classe. Le gros avantage, par rapport à
une fonction membre non-statique, c'est qu'elle peut être appelée sans
instance de la classe.
Il est généralement nécessaire d'y avoir recours pour des
fonctionnalités encapsulées dans une classe mais nécessitant un
passage de pointeur sur fonction (pour un classe CThread par exemple).
C'est en effet une des utilisations importantes, mais pas la seule. Je
dirais que la vaste majorité de mes fonctions statiques sont ou bien des
fonctions usine d'une sorte ou une autre, y comprise l'instance() du
singleton, ou bien des fonctions de « prétraitement » des paramètres
d'un constructeur. J'ai aussi un ou deux cas particuliers, qui me
servent dans une RTTI portable fait maison. Et une fois, évidemment, la
fonction que je passe à pthread_create. (Mais je fais des serveurs, sans
GUI. Je crois que dans les GUI, il y a beaucoup plus de callback.)
--
James Kanze GABI Software mailto:kanze@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
Anubis wrote in message
news:<c08k47$siq$...James Kanze wrote:Nicolas Aunai writes:je comprends l'intéret d'une variable static dans une classe,
mais pas celui d'une méthode static... que sont-elles et à quoi
servent-elles ?Elles sont des fonctions membres auxquelles on ne passe pas de
pointeur this.Le fait qu'elles n'aient pas le pointeur this par défaut en fait
surtout des fonctions (et non pas des méthodes) qui sont simplement
encapsulées dans la classe comme des fonctions le seraient dans un
namespace.
Elles ont bien accès à la partie privée de la classe. Elles font partie
integrale de l'interface de la classe.Le gros avantage est qu'une méthode statique est en tout point
similaire à une fonction (pointeurs, appels, etc).
Le gros avantage, par rapport à une fonction non-membre, c'est qu'elle a
accès à la partie privée de la classe. Le gros avantage, par rapport à
une fonction membre non-statique, c'est qu'elle peut être appelée sans
instance de la classe.Il est généralement nécessaire d'y avoir recours pour des
fonctionnalités encapsulées dans une classe mais nécessitant un
passage de pointeur sur fonction (pour un classe CThread par exemple).
C'est en effet une des utilisations importantes, mais pas la seule. Je
dirais que la vaste majorité de mes fonctions statiques sont ou bien des
fonctions usine d'une sorte ou une autre, y comprise l'instance() du
singleton, ou bien des fonctions de « prétraitement » des paramètres
d'un constructeur. J'ai aussi un ou deux cas particuliers, qui me
servent dans une RTTI portable fait maison. Et une fois, évidemment, la
fonction que je passe à pthread_create. (Mais je fais des serveurs, sans
GUI. Je crois que dans les GUI, il y a beaucoup plus de callback.)
--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16