Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

pointeurs de fonctions membre static, ca bloque :-(

15 réponses
Avatar
pasde.hcyrano.spam
bonsoir, je n'arrive pas a resoudre mon prob

/* pseudo code */

class MaClass {

/* static */

static bool check_A1(const int data);
static bool check_A2(const int data);
static bool check_A3(const int data);

static init_check();

/* comment declarer le tableau de pointeur de fonction membre static */

static bool (MaClass::*check[64])(const int discs_player); // ?????????


/* membre */

int discs[10];
int player;

bool uneMethode();

}

bool MaClass::check_A1(const int data) { .../...}
bool MaClass::check_A2(const int data) { .../...}
bool MaClass::check_A3(const int data) { .../...}

void MaClass::init_check() {
check[A1] = &MaClass::check_A1;
check[A2] = &MaClass::check_A2;
check[A3] = &MaClass::check_A2;
}

bool MaClass::uneMethode(int p) {

.../...

/*comment appeler une fonction de MaClass::check[] */

if((*(Maclass::check[p]))(discs[player])) { // ????????
.../...
}

.../...
}

merci pour votre aide
--
Bruno Causse
http://perso.wanadoo.fr/othello

10 réponses

1 2
Avatar
Roumillac Mathieu
Si j'ai bien compris tu veux déclarer un pointeur de fonction membre static.

En fait un pointeur de fonction membre static est de la même forme qu'un
pointeur de fonction, il n'a pas besoin de connaitre le type de l'objet
auquel la fonction appartient.

ex:
#include <cstdlib>
#include <iostream>

using namespace std;

class C{
public:
static void fonction();
}

void C::fonction(){
cout<<"fonction"<<endl;
}

int main(){
void (*p_fonction)() = C::fonction;
p_fonction();
return EXIT_SUCCESS;
}
Avatar
Sylvain
Bruno Causse wrote on 13/06/2006 23:05:
bonsoir, je n'arrive pas a resoudre mon prob

/* static */

static bool check_A1(const int data);
static bool check_A2(const int data);
static bool check_A3(const int data);


quel avantage par rapport à

bool check_A1(const int data);
bool check_A2(const int data);
bool check_A3(const int data);

si vous pensez en C, codez en C.
(ceci n'insinue aucune hiérarchie C vs C++)

/* comment declarer le tableau de pointeur de fonction membre static */


pourquoi déclarer le tableau de pointeur de fonction comme données
membre statique ??

static bool (MaClass::*check[64])(const int discs_player); // ?????????

/* membre */

int discs[10];
int player;

bool uneMethode();

}

bool MaClass::check_A1(const int data) { .../...}

void MaClass::init_check() {
check[A1] = &MaClass::check_A1;
}

bool MaClass::uneMethode(int p) {

/*comment appeler une fonction de MaClass::check[] */
if((*(Maclass::check[p]))(discs[player])) { // ????????
}
}


en C++ ?

si le traitement étant différant par la nature de l'objet traité, en
définissant:

class Medium {
virtual bool check(const int) = 0;
};

class Disc : public Medium {
bool check(const int data){
// ce qui était mis dans check_A1
}
};


ici vous semblez juste avoir besoin de savoir si un disc vérifie le
critère p; sortez les functions check de MaClass (cela ne la concerne
pas) et mettez ces fonctions dans un classe Disc avec une interface
permettant de demander à un disc (discs[player]) s'il vérifie 'p' ou
directement quelles conditions il vérifie (unique ou énumérées).

Sylvain.


Sylvain.

Avatar
kanze
Sylvain wrote:
Bruno Causse wrote on 13/06/2006 23:05:
bonsoir, je n'arrive pas a resoudre mon prob

/* static */

static bool check_A1(const int data);
static bool check_A2(const int data);
static bool check_A3(const int data);


quel avantage par rapport à

bool check_A1(const int data);
bool check_A2(const int data);
bool check_A3(const int data);


Ce sont deux choses différentes. Il n'y a pas d'« avantage »,
l'un par rapport à l'autre : on utilise celui qui a la
sémantique qui correspond au problème.

si vous pensez en C, codez en C.
(ceci n'insinue aucune hiérarchie C vs C++)


Quel rapport avec C -- il s'agit dans les deux cas des fonctions
membre.

/* comment declarer le tableau de pointeur de fonction
membre static */


pourquoi déclarer le tableau de pointeur de fonction comme
données membre statique ??


Parce que c'est ce qu'il lui faut dans l'application ? Vue
qu'il ne nous a pas dit ce qu'il essaie de faire (au niveau
abstrait), on ne peut pas juger si c'est la bonne solution ou
non.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
kanze
Bruno Causse wrote:
bonsoir, je n'arrive pas a resoudre mon prob

/* pseudo code */

class MaClass {

/* static */

static bool check_A1(const int data);
static bool check_A2(const int data);
static bool check_A3(const int data);

static init_check();

/* comment declarer le tableau de pointeur de fonction membre static */

static bool (MaClass::*check[64])(const int discs_player); // ?????????


Le type d'une fonction membre statique, c'est le même que le
type d'une fonction non-membre. Si « check » doit contenir des
pointeurs à des fonctions membre statique, il faut le déclarer :

static bool (*check[64])( int discs_player ) ;

Note aussi que puisque ce n'est qu'une déclaration ici, la
dimension est facultative.

/* membre */

int discs[10];
int player;

bool uneMethode();
}

bool MaClass::check_A1(const int data) { .../...}
bool MaClass::check_A2(const int data) { .../...}
bool MaClass::check_A3(const int data) { .../...}

void MaClass::init_check() {
check[A1] = &MaClass::check_A1;
check[A2] = &MaClass::check_A2;
check[A3] = &MaClass::check_A2;
}


Est-ce qu'il y a une raison d'écrire l'initialisation dans une
fonction, plutôt que de le faire statiquement :

bool (* MaClass::check[])( int ) =
{
&MaClass::check_A1,
&MaClass::check_A2,
// ...
} ;

Note bien qu'il faut la définition de toute façon, que tu
l'initialises dynamiquement ou non.

Aussi, si tu ne modifies pas la valeur des entrées par la suite,
je conseillerais de le rendre const :

static bool (*const check[])( int ) ; // déclaration (dans la
classe).

bool (*const MaClass::check[])( int ) =
{
&MaClass::check_A1, /* ... */
} ;

(Si c'est const, évidemment, l'initialisation dans une fonction
est interdite. Il faut l'initialiser dans la définition, comme
ici.)

bool MaClass::uneMethode(int p) {

.../...
/*comment appeler une fonction de MaClass::check[] */
if((*(Maclass::check[p]))(discs[player])) { // ????????


S'il s'agit bien des fonctions statiques :

if ( (*check[ p ])( discs[ player ] ) ) {

Si les fonctions ne sont pas statiques (et le type du tableau
est des pointeurs aux fonctions membres), il faut utiliser
l'opérateur .* ou ->*, ce qui implique un objet ou un pointeur
explicit ; le this implicite ne vaut plus. On écrirait alors :

if ( (this->*(check[ p ]))( discs[ player ] ) ) {

(Je ne crois pas que les (...) autour de check[p] soit
nécessaire. Mais je préfère les mettre ; je ne suis pas toujours
100% sûr des précédances des opérateurs si peu utilisés.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Sylvain
kanze wrote on 14/06/2006 10:32:

quel avantage par rapport à


Ce sont deux choses différentes. Il n'y a pas d'« avantage »,
l'un par rapport à l'autre : on utilise celui qui a la
sémantique qui correspond au problème.


tu ne commentes pas ce que j'ai écrit, donc ...

si vous pensez en C, codez en C.
(ceci n'insinue aucune hiérarchie C vs C++)


Quel rapport avec C -- il s'agit dans les deux cas des fonctions
membre.


où as-tu vu un "class/struct QlqChose" devant mes "bool check_Ai" ??


/* comment declarer le tableau de pointeur de fonction
membre static */


pourquoi déclarer le tableau de pointeur de fonction comme
données membre statique ??


Parce que c'est ce qu'il lui faut dans l'application ? Vue
qu'il ne nous a pas dit ce qu'il essaie de faire (au niveau
abstrait), on ne peut pas juger si c'est la bonne solution ou
non.


où ai-je porté un jegement ?

Sylvain.



Avatar
Bruno CAUSSE
dans l'article , kanze à
a écrit le 14/06/06 10:45 :

[...]

Merci maintenant ca fonctionne :-)

Mais c'est loin d'etre evident pour le simple boetien que je suis.

J'ai meme eu du mal a comprendre pourquoi entre ta solution et celle de
fabien il manquait les * et & , oui :-) a cause du typedef.

Mais plein de choses m'echappent, par ex:

Utilisation a l'interieur d'une methode membre

((this)->*(function[id]))(param)

Et dans une methode d'une autre classe

((objet)->*(objet.function[id]))(param) pourquoi le 2e "objet"?
Avatar
kanze
Bruno CAUSSE wrote:
dans l'article , kanz e à
a écrit le 14/06/06 10:45 :

[...]

Merci maintenant ca fonctionne :-)

Mais c'est loin d'etre evident pour le simple boetien que je suis.


Le C++ est un langage assez complexe, qui exige un certain
apprentissage. Et une attention assez poussée aux détails : des
distinctions du genre déclaration / définition ou initialisation
/ affectation sont parfois d'une grande importance, même si la
distinction n'est pas toujours claire pour un débuttant.

J'ai meme eu du mal a comprendre pourquoi entre ta solution et
celle de fabien il manquait les * et & , oui :-) a cause du
typedef.


Non seulement. Lors de l'utilisation, il y a des conversions
implicites, etc., qui fait que certains opérateurs sont parfois
facultatifs. Moi, je les mets quand même, en général, parce que
je trouve que ça rend plus clair ce qu'on fait, mais d'autres
les laissent systèmatiquement. Donc :

extern int f() ;
int (*pf)() ; // C'est un pointeur à une fonction...
pf = &f ; // On l'initialise avec l'adresse de f.
pf = f ; // Aussi. Il y a conversion implicite.

(*pf)() ; // On appelle la fonction...
pf() ; // Aussi... on peut se servir d'un
// pointeur à une fonction exactement
// comme le nom d'une fonction.

En gros, pour des raisons historiques, on peut utiliser le nom
d'une fonction et son adresse de façon interchangeable ; le
compilateur comprend d'après le contexte ce qu'il faut, et fait
les conversions nécessaire. Personellement, je choisis d'être
explicit quand même, mais il y a une grande tradition qui fait
le contraire, et il y a même certains idiomes (avec les
templates) qui y compte.

Mais plein de choses m'echappent, par ex:

Utilisation a l'interieur d'une methode membre

((this)->*(function[id]))(param)


Attention : il s'agit ici de l'utilisaton d'un pointeur à
fonction membre (non-statique). La syntaxe autour des pointeurs
à membre est assez complex ; à ta place, j'attendrais avoir
maîtriser des bases avant de s'y venturer, d'autant plus que ce
n'est pas souvent utile, et jamais nécessaire. J'aborderais même
les templates avant -- non qu'ils soient moins complexe, mais
ils sont de beaucoup plus utiles.

Et dans une methode d'une autre classe

((objet)->*(objet.function[id]))(param) pourquoi le 2e "objet"?


Parce que fonction est un membre (non-statique). Sans
l'« objet », c'est implicitement comme si on avait écrit
« this->function » ; c-à-d qu'on accederait au tableau membre
de cet objet, et non à celui de l'objet « objet ». (En
revanche, l'expression telle que tu l'as réproduit ci-dessus ne
peut pas être légal. Si « objet » est un pointeur,
« objet.function » ne passe pas, parce que l'opérand de gauche
de l'opérateur « . » doit avoir un type classe, et non un type
pointeur. En revanche, l'opérand de gauche de « ->* » doit
obligatoirement être un pointeur.) La forme correcte serait donc
soit :
(objet->*(objet->function[id]))( param ) ;
si objet a un type pointeur, soit :
(objet.*(objet.function[id]))( param ) ;
si objet a un type de classe.

Dans les deux cas, le sous-expression « (objet.function[id]) »
ou « (objet->function[id]) » lit un pointeur à fonction membre
du tableau dans l'objet désigné par « objet », et appelle la
fonction membre qu'il désigne sur l'objet désigné par
« objet ». L'objet désigné par « objet » sert bien deux
fois, et chaque fois, on pourrait très bien utiliser un autre
objet, de façon indépendante.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Fabien LE LEZ
On Wed, 14 Jun 2006 15:33:28 +0200, Bruno CAUSSE :

Mais c'est loin d'etre evident pour le simple boetien que je suis.


Je te comprends. Bien qu'ayant quelques années d'expérience en C++, je
ne comprends toujours pas grand-chose aux pointeurs de fonctions. Ça
fait partie des "coins poussiéreux" du langage, dont je ne me sers
quasiment jamais.

Avatar
Jean-Claude Arbaut
Fabien LE LEZ wrote:
On Wed, 14 Jun 2006 15:33:28 +0200, Bruno CAUSSE :


Mais c'est loin d'etre evident pour le simple boetien que je suis.



Je te comprends. Bien qu'ayant quelques années d'expérience en C++, je
ne comprends toujours pas grand-chose aux pointeurs de fonctions. Ça
fait partie des "coins poussiéreux" du langage, dont je ne me sers
quasiment jamais.



C'est très différent des pointeurs de fonction du C ?


Avatar
Olivier Miakinen

Je te comprends. Bien qu'ayant quelques années d'expérience en C++, je
ne comprends toujours pas grand-chose aux pointeurs de fonctions. Ça
fait partie des "coins poussiéreux" du langage, dont je ne me sers
quasiment jamais.


C'est très différent des pointeurs de fonction du C ?


Si j'ai bien compris leurs réponses, Matthieu et kanze avaient l'air de
penser que non.

Mais je pense que, dans de nombreux cas où l'utilisation de pointeurs
de fonctions peut s'avérer utile en C, on pourrait s'en sortir avec des
sous-classes et des fonctions virtuelles en C++. C'est en ce sens que je
comprends la remarque de Fabien : ça existe, il y a probablement des cas
où ce sera utile même en C++, mais il n'a quasiment jamais rencontré de
tels cas.

--
Olivier Miakinen
Troll du plus sage chez les conviviaux : le nouveau venu, avec
son clan, s'infiltre dans les groupes de nouvelles. (3 c.)


1 2