OVH Cloud OVH Cloud

[débutant objet] tableau de pointeur de fonction

47 réponses
Avatar
cyrcocq
Bonjour,

Je définis une classe qui me permet de générer des formes d'ondes (extraits
code en fin de message(toutes critiques bienvenues ;-) ))
Dans cette classe, j'ai quelques fonctions,
de type
void F0 (double);

Je veux faire un tableau de pointeurs de fonctions mais je rencontre
quelques difficultés.

J'essaie de faire un
typedef void (*fptronde) (double);

puis je fais des

fonction[0]=&onde::F0;

Mais ça ne compile pas... error C2440: '=' : impossible de convertir de
'void (__thiscall onde::* )(double)' en 'onde::fptronde'

Allors 3 questions:

comment dois-je définir mon type de pointeur sur fonction???

suis-je obligé de passer par un type que je n'utilise qu'une fois?

Les données étant dupliquées pour chaque instance de la classe, que dois-je
faire pour n'avoir qu'une instance de ce pointeur de fonction?

Merci.






class onde
{
private:

double Amp, *PAmp, Freq, *PFreq, Deph, *PDeph, Off, *POff; //Amplitude
Frequence déphasage offset (numériques fixes) et pointeurs associés.

typedef void (*fptronde) (double);

fptronde fonction [5];

void sinusoide(double);
void carree (double);
void triangulaire (double);
void montante (double);
void descendante (double);

public:

int type; //type de générateur d'onde
double sortie;
bool zero;

onde();
double CalcSortie(double);
void SetAmplitude(double);
void LieAmplitude(double&);
void SetFrequence(double);
void LieFrequence(double&);
void SetDephasage(double);
void LieDephasage(double&);
void SetOffset(double);
void LieOffset(double&);
};

void onde::sinusoide(double t)
{
sortie= *PAmp * sin( *PFreq * t + *PDeph ) + *POff;
}
(...)
onde::onde()
{
Amp=Freq=Deph=Off=0;
PAmp=&Amp;
PFreq=&Freq;
PDeph=&Deph;
POff=&Off;
type=0;

fonction[0]=&onde::sinusoide;
fonction[1]=&onde::carree;
fonction[2]=&onde::triangulaire;
fonction[3]=&onde::montante;
fonction[4]=&onde::descendante;
}

double onde::CalcSortie(double t)
{
double temp=*PFreq * t;
(*(fonction[type]))(t);
}

void onde::SetAmplitude(double A)
{
Amp=A;
PAmp=&Amp;
}
void onde::LieAmplitude(double &A)
{
PAmp=&A;
}
(...)

10 réponses

1 2 3 4 5
Avatar
cyrcocq
"Fred" a écrit dans le message de news:
yGEYe.3992$
Bon, en m'aidant un peu de google, j'ai trouvé la syntaxe pour appeler les
pointeurs de méthode. Ca compile, par contre, je ne garantis pas que ça
marche :)


Effectivement, l'esprit était là!
Merci

En simplifiant au max en restant général ca fait

class MaClasse
{
public:
double A;
typedef void (MaClasse::*fptrMaClasse) (double);
MaClasse (void);
void Calc(double);
static fptrMaClasse fonction [1];
void f0(double);
};
void MaClasse::f0(double t)
{
A=t; //(ou autre)
}

MaClasse::MaClasse()
{
fonction[0]=&MaClasse::f0;
}

void MaClasse::Calc(double t)
{
//C'est vrai que ça ça tue!!!
// Je trouve qu'il faut beaoucoup de parenthéses pour en arriver là:
((this)->*(fonction[0])) (t);
}





Bon maintenant je me lance dans l'analyse des foncteurs et je suis les
conseils de Fabien!

Ah... quelle joie, je vais dormir tranquille cette nuit!



Merci à tous

Avatar
kanze
cyrcocq wrote:

Je définis une classe qui me permet de générer des formes
d'ondes (extraits code en fin de message(toutes critiques
bienvenues ;-) )) Dans cette classe, j'ai quelques fonctions,
de type

void F0 (double);


Des fonctions membre, qui utilise le this, ou non ?

Je veux faire un tableau de pointeurs de fonctions mais je
rencontre quelques difficultés.

J'essaie de faire un
typedef void (*fptronde) (double);


C'est l'adresse d'une fonction libre (non membre) ou d'une
fonction membre statique. Puisque pour l'appeler, il faut un
objet (du bon type), le type d'un pointeur à fonction membre
doit contenir le nom de la classe, c-à-d :

typedef void (onde::*fptronde)( double ) ;

puis je fais des

fonction[0]=&onde::F0;


Selon le cas :

-- si les fonctions sont des membres non statiques, il faut que
function ait le type fptronde[], avec fptrond déclaré comme
ci-dessus, mais

-- si les fonctions sont des membres statiques, ta déclaration
de fptronde est le bonne.

Mais ça ne compile pas... error C2440: '=' : impossible de
convertir de 'void (__thiscall onde::* )(double)' en
'onde::fptronde'


Je conclus donc que tes fonctions ne sont pas statiques:-).

Note que pour appeler ces fonctions, il va falloir un objet ou
un pointeur à un objet, même à l'intérieur d'une autre fonction
membre. Quelque chose du genre :

(this->*(function[i]))( unDouble ) ;

Note aussi l'utilisation de l'opérateur ->*, à la place de ->.

Allors 3 questions:

comment dois-je définir mon type de pointeur sur fonction???


Voir ci-dessus.

suis-je obligé de passer par un type que je n'utilise qu'une
fois?


Je suppose que ta question est plutôt, est-ce que le typedef est
nécessaire. La réponse est non. Mais beaucoup des gens trouvent
que c'est plus lisible ; sans le typedef, le tableau devient :

void (onde::*function[ N ])( double ) ;

Aussi : un typedef ne définit pas un type. Il déclare un nouveau
*nom* pour un type existant. Mais il n'y a que le nom qui est
nouveau ; c'est toujours le même type.

Les données étant dupliquées pour chaque instance de la
classe, que dois-je faire pour n'avoir qu'une instance de ce
pointeur de fonction?


Le déclarer comme membre statique ?

class onde
{
private:

double Amp, *PAmp, Freq, *PFreq, Deph, *PDeph, Off, *POff; //Amplitu de
Frequence déphasage offset (numériques fixes) et pointeurs associés.


C'est de très mauvais style de mettre plus d'une définition par
instruction.

typedef void (*fptronde) (double);


typedef void (onde::*fptronde)( double ) ;

fptronde fonction [5];


Si le contenu du tableau sera toujours pareil :

static fptronde const fonction[ 5 ] ;

void sinusoide(double);
void carree (double);
void triangulaire (double);
void montante (double);
void descendante (double);

public:

int type; //type de générateur d'onde
double sortie;
bool zero;


Des données publiques, ce n'est pas en général très bon non
plus.

onde();
double CalcSortie(double);
void SetAmplitude(double);
void LieAmplitude(double&);
void SetFrequence(double);
void LieFrequence(double&);
void SetDephasage(double);
void LieDephasage(double&);
void SetOffset(double);
void LieOffset(double&);
};

void onde::sinusoide(double t)
{
sortie= *PAmp * sin( *PFreq * t + *PDeph ) + *POff;
}

(...)
onde::onde()
{
Amp=FreqÞph=Off=0;
PAmp=&Amp;
PFreq=&Freq;
PDeph=&Deph;
POff=&Off;
type=0;

fonction[0]=&onde::sinusoide;
fonction[1]=&onde::carree;
fonction[2]=&onde::triangulaire;
fonction[3]=&onde::montante;
fonction[4]=&onde::descendante;
}


Si fonction est statique, pas besoin de l'initialiser dans
chaque constructeur. Quelque chose du genre :

onde::fptronde const onde::fonction[] =
{
&onde::sinusoide,
&onde::carree,
&onde::triangulaire,
&onde::montante,
&onde::descendante,
} ;

dans un .cpp quelconque fait l'affaire.

double onde::CalcSortie(double t)
{
double temp=*PFreq * t;
(*(fonction[type]))(t);
}


Pas trop compris. Tu calcules une valeur temp, puis tu ne t'en
sers jamais.

void onde::SetAmplitude(double A)
{
Amp=A;
PAmp=&Amp;
}
void onde::LieAmplitude(double &A)
{
PAmp=&A;
}
(...)


Sans savoir le but de la classe, c'est difficile à dire plus.
Mais a priori, je crois que je chercherai plutôt dans la
direction de l'héritage -- peut-être des mix-in avec la fonction
d'une côté, et une classe pour chacune des valeurs de l'autre.
Quelque chose du genre :

class Onde
{
public:
virtual ~Onde() {}
double operator()( double t ) const
// C'est le nom conventionnel,
// à la place de CalcSortie.
{
return f( t ) ;
}
private:
virtual double amp () const = 0 ;
virtual double freq () const = 0 ;
virtual double deph () const = 0 ;
virtual double offset() const = 0 ;

virtual double f( double t ) const = 0 ;
// Incroyable. Un cas où le nom
// f() convient réelement.
} ;

class Sinusoide : public virtual Onde
{
private:
virtual double f( double t ) const
{
return amp() * sin( freq() * t + deph() ) + offset() ;
}
} ;
// Pareil pour les autres fonctions...

class Valeur
{
public:
explicit Valeur( double initial = 0.0 )
: myValeur( initial )
{
}
void set( double v )
{
myValeur = v ;
}
double get() const
{
return myValeur ;
}
private:
double myValeur ;
} ;

class Ref
{
public:
explicit Ref( double* initial = NULL )
: myRef( initial )
{
}
void lie( double* newRef )
{
myRef = newRef ;
}
void set( double v )
{
*myRef = v ;
}
double get() const
{
return *myRef ;
}
private:
double* myRef ;
} ;

template< typename Base > // Base doit être ou Valeur, ou
Ref
class Amp : public Base, public virtual Onde
{
private:
virtual double amp() const
{
return this->get() ;
}
} ;
// Pareil pour Freq, Deph, et Offset...
// (Peut-être à l'aide des macros...)

template< typename Fnc,
typename AmpBase,
typename FreqBase,
typename DephBase,
typename OffBase >
class ConcreteOnde
: public virtual Onde
, private Fnc
, private Amp< AmpBase >
, private Freq< FreqBase >
, private Deph< DephBase >
, private Offset< OffBase >
{
}

et on crée des objets au moyen de :

new ConcreteOnde< Sinusoide, Valeur, Ref, Valeur, Valeur > ;

--
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
Fabien LE LEZ wrote:
On Thu, 22 Sep 2005 21:34:03 +0200, "cyrcocq" :

Donc si je comprends bien (Stan et Fabien) l'approche tableau
de pointeur de fonction est a remplacer par une approche de
foncteur.


Oui. En rappelant que le type canonique pour un tableau en C++
est std::vector<>.


Ça dépend. Si on prend sa première version, comme vas-tu faire
pour initialiser le tableau statique. C'est un des cas où les
vieux tableaux de C font encore mieux l'affaire :

onde::fptronde const fonction[] =
{
&onde::sinusoide,
// ...
} ;

Note qu'on peut le définir const, et qu'avec l'écriture
ci-dessus, c'est une initialisation statique, sans problèmes de
l'ordre d'initialisation. (Sûrement pas un problème ici, mais
dans certains cas...)

--
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
Fabien LE LEZ wrote:
On Thu, 22 Sep 2005 13:41:25 +0200, "cyrcocq" :

fptronde fonction [5];


Et un jour, tu ajouteras une fonction, et, ne te souvenant
plus de la signification (ou de l'existence) de ce "5", tu ne
le modifieras pas... et boum !

Je corrige donc cette faute de frappe :

std::vector <fptronde> fonction;


Sauf que par le suite, il a bien dit qu'il n'en voulait qu'une
copie en tout, et non une copie par objet. Et d'après ce qu'il
nous a montré, le tableau pourrait bien être const. Donc :

static fptronde const fonction[] ;

Autre souci : indexer ton tableau avec des entiers ne me
paraît pas adéquat. Que diable le "3" de "fonction[3]" ou de
"type=3" peut-il bien signifier ?

Il vaudrait mieux créer un type "Index", et mettre tes
fonctions dans un std::map<Index,type_fonction>.


Ce n'est pas un peu un marteau piqueur pour écraser une mouche.
Pourquoi pas simplement :

enum Fonctions
{
sinusoide,
carree,
triangulaire,
montante,
descendante,

endFonctions
} ;
static fptronde const function[ endFonctions ] ;

Si c'est la logique interne du programme qui choisit la fonction,
Index sera un enum :

enum Index { FCT_carre, FCT_sinus, ... };


Tout à fait. Et l'implémentation la plus simple d'un map de ce
genre d'enum, c'est encore les tableaux de type C.

Si c'est l'utilisateur qui choisit la fonction, l'index pourra
être le texte affiché dans le menu, pour éviter les
intermédiaires :


Et poser des problèmes énormes lors de
l'internationalisation:-).

Plus généralement, on ne se sert *jamais* du texte d'une
interface utilisateur directement. Parce que c'est sûr qu'il va
changer.

Ce qui est probable, c'est qu'on a un map entre les string et
des valeurs d'enum quelque part. (Map initialisé à partir des
fichiers de config, en fonction de l'environement linguistique,
évidemment. Mais on ne veut pas charger Onde de tout ça.)

--
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
cyrcocq wrote:
"Fabien LE LEZ" a écrit dans le
message de news:

std::vector <fptronde> fonction;


Bon, je vois... ici ca rigole pas ;-)


C'est une réaction « knee jerk ». (Je m'excuse, mais je ne
connais pas l'équivalent en français.) En fait, tu te trouves
dans un des rares cas où std::vector est nettement inférieur aux
bons vieux tableaux de C.

Non, c'est chouette d'apprendre à faire et aussi d'apprendre à
faire corectement, mais j'avoue que là j'ai un peu peur de pas
tout maîtriser.


Qu'est-ce que tu vas dire de ma solution, alors, avec des
mix-ins ? :-)

Faut dire que je débute l'aspect objet, je ne sais pas si je
peux déjà dire que j'ai commencé la librairie standard... J'ai
l'impression de devoir tout apprendre d'un bloc. Bref beaucoup
de notions à assimiler!


Oui, mais pas forcement d'un bloc. Apprendre toutes les
subtilités de la STL, ce n'est pas pour tout de suite. Apprendre
comment utiliser des std::vector à la place d'un tableau de type
C, en revanche, n'est pas difficile. Au contraire, dans la
plupart des cas (bien qu'on se trouve dans l'exception ici),
std::vector est même plus simple qu'un tableau de type C.

Autre souci : indexer ton tableau avec des entiers ne me
paraît pas adéquat. Que diable le "3" de "fonction[3]" ou de
"type=3" peut-il bien signifier ?

Il vaudrait mieux créer un type "Index", et mettre tes
fonctions dans un std::map<Index,type_fonction>.

Si c'est la logique interne du programme qui choisit la
fonction, Index sera un enum :

enum Index { FCT_carre, FCT_sinus, ... };

Si c'est l'utilisateur qui choisit la fonction, l'index
pourra être le texte affiché dans le menu, pour éviter les
intermédiaires :

typedef std::string Index;


Hmmm... Je vois... ou plutot, je vais réflechir à la question
et je verrais!


Ne fais pas compliquer juste pour faire compliquer. L'idée de
l'enum est bonne -- Fabien a bien raison à dire que type = 3
n'est pas particulièrement parlant (et qu'on risque facilement
de s'y tromper). Aller au delà... ? Ça me semble même plutôt
melanger des concernes qui doivent rester séparés : les Ondes
n'ont rien à foutre avec la représentation textuelle des noms de
leurs fonctions -- c'est le boulot de quelqu'un d'autre, si
c'est nécessaire.

typedef void (*fptronde) (double);

comment dois-je définir mon type de pointeur sur fonction???


Comme un foncteur.


J'ai bien l'impression que vous étes d'accord sur cet aspect!


Pas réelement. Je m'aligne plutôt avec Pascal Pizeine, pour la
fonction virtuelle dans la classe de base. (En passant, ça
s'appelle le concepte de modèle, ou « template design pattern »
en anglais. À ne pas confondre avec les templates du C++, quand
même.)

Ceci dit, on pourrait très bien considérer le concepte de
stratégie, avec un objet fonctionnel comme délégué. Mais
attention alors au vocabulaire -- ce n'est pas l'objet
fonctionnel de la STL, qui lui, sera copié par valeur, et dont
le type réel est résolu à la compilation.

En fait, tout dépend de la souplesse dont tu as besoin. S'il
faut changer dynamiquement le type de fonction d'un objet
existant, il n'y a que le concept de stratégie -- la délégation
-- qui le permet. Si le type fonctionnel de l'objet reste
constant, mais il n'est déterminé que lors de la création de
l'objet, le concept de modèle me semble la solution la plus
simple (mais la délégation reste aussi possible). Et enfin, si
on peut permettre de fixer le type fonctionnel lors de la
compilation, on pourrait s'en tirer avec des templates et des
objets fonctionnels à la STL. On perd énormement de souplesse,
mais on gagne nettement en vitesse. (La différence n'est
normalement pas sensible, mais tes fonctions on l'air d'être
bien petites... et du genre qu'on risque de les appeler des
millions de fois.)

En passant, une fois qu'on a compris les concepts, il est
rélativement facile de passer d'un à l'autre -- surtout entre le
« template pattern » et la programmation avec des templates à la
STL.

Tant pis pour ma tentative d'assimilation progressive (basée
sur la succession des chapitres du cours de Christian
Casteyde)


Je ne crois pas que ce soit un bon début. Pour commencer, il
prétend enseigner du C/C++. Langage qui n'existe pas -- le C et
le C++ sont bien deux langages distincts, avec leurs propres
idiomes, même si le C++ s'est basé sur le C au début, et qu'il y
a un sous-ensemble commun. Je conseillerais plutôt un texte
uniquement sur le C++, et assez moderne. (Ça fait un moment que
je n'ai pas régardé un livre C++ pour débuttants, mais d'après
tout ce que j'entends, "Accelerated C++: Practical Programming
by Example", de Koenig et Moo, serait parmi les meilleurs, sinon
le meilleur.)

Mais n'attends pas à tout trouver dans un seul texte. Le C++ est
un langage extrèmement souple, avec beaucoup de façons de
résoudre n'importe quel problème. Et les auteurs ne présentent
en général que leur méthode préférée -- qui ne serait pas
forcement la tienne.

Decidemment, c'est frustrant de ne pas avoir trouvé/compris la
méthode pour utliser ce tableau de pointeur de fonction, il
faut quand même que j'y revienne...


En général, les pointeurs à des fonctions membre est considéré
un topique avancé. Pas quelque chose qu'on aborde dès le début.
(Et certainement pas quelque chose qu'on aborde avant d'avoir
compris les fonctions virtuelles, ou l'utilisation des templates
-- l'utilisation d'un template bien conçue est rélativement
simple, même si bien concevoir et bien implémenter une classe
template ne l'est pas toujours.)

typedef void (onde::*fptronde) (double);
// On est d'accord, je définis un type pointeur de fonction de ma classe
onde
static fptronde fonction [5];
// Je déclare un tableau de 5 de ces pointeurs
fonction[0]=&onde::sinusoide;
// J'initialise le premier pointeur de mon tableau
fonction[0] (t);
//Me dit:error C2064: le terme ne correspond pas à une fonction
//Pareil avec onde::fonction[type] (t); ou this->fonction[type] (t); ou
*fonction[0] (t);


C'est une particularité de beaucoup de posters, de ne répndre
qu'à la question posée. Or qu'il est évident que si tu ne
sais pas déclarer un pointeur à une fonction membre, tu ne sais
pas t'en servir non plus. Voir ma réponse à ton posting initial.

Note bien aussi quand même que les pointeurs à des fonctions
membre est considéré un sujet avancé, et qu'en général,
l'utilisation ou de l'héritage ou des objets fonctionnels est
souvent considérée plus simple.

--
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
Stan
"kanze" a écrit dans le message de news:

J'ai bien l'impression que vous étes d'accord sur cet aspect!

Pas réelement. Je m'aligne plutôt avec Pascal Pizeine, pour la


Avec quoi exactement tu n'est pas d'accord ?


--
-Stan

Avatar
Fabien LE LEZ
On 23 Sep 2005 00:46:13 -0700, "kanze" :

Ça dépend. Si on prend sa première version, comme vas-tu faire
pour initialiser le tableau statique.


Dans sa première version, il n'y a pas de tableau statique, vu que
c'est un membre non-static non-const de sa classe.

Mais je suis d'accord avec toi sur le principe : pour un tableau ou
une chaîne static const, les tableaux à la C font de l'usage. Désolé
pour cette imprécision.

Avatar
kanze
Stan wrote:
"kanze" a écrit dans le message de news:

J'ai bien l'impression que vous étes d'accord sur cet
aspect!

Pas réelement. Je m'aligne plutôt avec Pascal Pizeine, pour la


Avec quoi exactement tu n'est pas d'accord ?


Qu'il faut des objets fonctionnels. C'est sûr que comme
solution, c'est préférable aux pointeurs aux fonctions membres,
mais comme solution de son problème, on pourrait bien envisager
autres choses. La plus simple, probablement, étant le modèle de
conception « template ».

--
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 23 Sep 2005 01:31:23 -0700, "kanze" :

std::vector <fptronde> fonction;


Bon, je vois... ici ca rigole pas ;-)


C'est une réaction « knee jerk ».


Non, une solution inadaptée à un problème réel.


class onde
{
[...]
fptronde fonction [5];


Cette dernière ligne est AMHA fausse.
S'il faut un tableau non-"static const", qu'on remplit dans le
constructeur, la réponse est std::vector<>.

En fait, il ne fallait pas un tableau non-"static const", donc ma
réponse était effectivement à côté de la plaque, d'un point de vue
plus global.



Avatar
cyrcocq
J'espère que ce message ne sera pas trop déplacé, je reprends ici un peu ce
que Kanze a dit sur différents messages du fil.

Les citations seront donc complètement désordonnées et sorties de leur
contexte de départ...



J'ai étudié les proposition de Stan Kanze et Fabien. J'ai du y perdre
quelques cheveux. Mais entre cet exercices de compréhension et les
différents messages du fil, j'ai vraiment beaucoup appris!!!

Probablement plus encore avec celle de kanze et ces virtual multiples !





Non, c'est chouette d'apprendre à faire et aussi d'apprendre à
faire correctement, mais j'avoue que là j'ai un peu peur de pas
tout maîtriser.


Qu'est-ce que tu vas dire de ma solution, alors, avec des
mix-ins ? :-)




la
fonction virtuelle dans la classe de base. (En passant, ça
s'appelle le concept de modèle, ou « template design pattern »




J'ai quand même fini par comprendre... en gros!

D'ici à ce que je me mette à utiliser ces principes va falloir que je
m'entraine un moment!

Ce qui me parait le plus hallucinant là dedans c'est que ça donne
l'impression de remonter l'édifice par la fin!

On part d'un objet qui quasi vide et c'est en les spécialisant qu'on le
remplit. Moi ça me tue!





Sauf que par la suite, il a bien dit qu'il n'en voulait qu'une
copie en tout, et non une copie par objet. Et d'après ce qu'il
nous a montré, le tableau pourrait bien être const. Donc :

static fptronde const fonction[] ;




Exact sur toute la ligne



Ceci dit, on pourrait très bien considérer le concept de
stratégie, avec un objet fonctionnel comme délégué. Mais
attention alors au vocabulaire -- ce n'est pas l'objet
fonctionnel de la STL, qui lui, sera copié par valeur, et dont
le type réel est résolu à la compilation.

En fait, tout dépend de la souplesse dont tu as besoin. S'il
faut changer dynamiquement le type de fonction d'un objet
existant, il n'y a que le concept de stratégie -- la délégation
-- qui le permet.




Hum... la faudrait qu'on m'explique parce que justement c'est là que toutes
les solutions proposées coincent...

Oui, j'ai mon générateur d'onde qui change de forme d'onde.



Donc si je comprend bien, je devrais avoir 2 objets indépendants.

L'un s'occupant des paramètres (amplitude fréquence...)

L'autre de la génération de l'onde.



Si j'ai bien compris, même en le disant ça me parait abordable!



Si le type fonctionnel de l'objet reste
constant, mais il n'est déterminé que lors de la création de
l'objet, le concept de modèle me semble la solution la plus
simple (mais la délégation reste aussi possible). Et enfin, si
on peut permettre de fixer le type fonctionnel lors de la
compilation, on pourrait s'en tirer avec des templates et des
objets fonctionnels à la STL. On perd énormément de souplesse,
mais on gagne nettement en vitesse. (La différence n'est
normalement pas sensible, mais tes fonctions on l'air d'être
bien petites... et du genre qu'on risque de les appeler des
millions de fois.)




Effectivement, les appels seront fréquents nombreux...

Je cherche à générer et jouer en direct des ondes sonores liées les unes
aux autres.

(offset de l'une pouvant être la sortie d'une autre, 2 pouvant partager un
paramètre...)

Ces ondes pouvant changer d'enveloppe (de fonction) soudainement...

Bref, je vais avoir besoin de calculer la sortie de tous mes générateurs
d'ondes (et de mes effets ultérieurement) environs 44100 fois par
secondes...

J'ai peur d'être un peu juste... peut être que je devrais revenir au C sur
une idée aussi folle?



En général, les pointeurs à des fonctions membre est considéré
un topique avancé.


En fait c'est cet aspect vitesse qui m'a fait imaginer une telle méthode.
(Je n'ai toujours pas complètement abandonné l'idée!)



double Amp, *PAmp, Freq, *PFreq, Deph, *PDeph, Off, *POff;
//Amplitude
Frequence déphasage offset (numériques fixes) et pointeurs associés.


C'est de très mauvais style de mettre plus d'une définition par
instruction.


Ah? Pourtant dans le principe de ce que j'avais fait au début, je trouvais
ça
abordable, pas lourd...



Ça fait un moment que
je n'ai pas regardé un livre C++ pour débutants, mais d'après
tout ce que j'entends, "Accelerated C++: Practical Programming
by Example", de Koenig et Moo, serait parmi les meilleurs, sinon
le meilleur.




Bon... et bien je vais envisager l'achat de cet ouvrage (ou d'un autre, je
vais quand même aller faire un tour sur les différentes FAQ C++ du net)

Dommage, je suis actuellement chercheur d'emploi (Ingénieur systèmes et
réseau Microsoft en recherche dans la moitié Sud ou La moitié Ouest de la
France...) et mes moyens sont limités!





Sinon, une nouvelle question sur la validité de mon code de départ a surgi
suite à mes approfondissements du jour

J'avais dans ma classe des données membres Amp et des *PAmp.

Dans une fonction je faisais un PAmp=&Amp

Mais j'ai lu qu'un membre d'une classe ne pouvait s'adresser directement

Ce qui signifierai que si j'avais une classe "onde" avec un membre "double
amp"

Je ne pouvais pointer dessus qu'avec un "double onde::*" et non avec un
"double *"

C'est vrai?


1 2 3 4 5