2017-02-16 1 views
0

Here's my code:Comment puis-je "envoyer automatiquement" l'instance de l'objet appelant dans la fonction de liaison?

#include <iostream> 
#include <functional> 
#include <vector> 

class Voice 
{ 
public: 
    double mVoiceValue = 0.0; 
    std::function<double(Voice &, double)> mTargetFunction; 

    Voice(std::function<double(Voice &, double)> targetFunction) : mTargetFunction(targetFunction) { } 
    ~Voice() { }  

private: 
}; 

class Osc 
{ 
public: 
    double mOscValue = 1.0; 

    Osc() { } 
    ~Osc() { } 

    double Modulate(Voice &voice, double value) { 
     return mOscValue * voice.mVoiceValue * value; 
    } 

private: 
}; 

int main() 
{ 
    Osc *osc = new Osc(); 
    Voice voice1(std::bind(&Osc::Modulate, osc, std::placeholders::_1, std::placeholders::_2)); 
    Voice voice2(std::bind(&Osc::Modulate, osc, std::placeholders::_1, std::placeholders::_2)); 

    voice1.mVoiceValue = 1.0; 
    voice2.mVoiceValue = 2.0; 
    std::cout << "value: " << voice1.mTargetFunction(voice1, 10.0) << std::endl; 
    std::cout << "value: " << voice2.mTargetFunction(voice2, 100.0) << std::endl; 
} 

Je voudrais non passer les instances voice1/voice2 (à savoir lui-même) à la fonction de liaison d'appel. Puisque je voudrais envoyer directement cette instance parce que c'est la même chose de l'objet appelant.

Comment puis-je lier de cette manière?

dire qu'il doit retourner les mêmes résultats Vocation:

std::cout << "value: " << voice1.mTargetFunction(10.0) << std::endl; 
std::cout << "value: " << voice2.mTargetFunction(100.0) << std::endl; 
+0

Fournit une méthode sur 'Voice' qui appelle' mTargetFunction (* this, whatever); '. Puis appelez-le comme 'voice1.callTarget (10.0);' –

+1

Sachez que vous faites 2 copies de l'objet 'osc' lorsque vous liez. – Slava

+0

@Slava: que voulez-vous dire par "vous faites 2 copies d'osc"? – markzzz

Répondre

0

Si c'est bon pour le constructeur Voice de prendre deux arguments (l'objet Osc et le pointeur de fonction membre), vous pouvez résoudre quelque chose comme ça :

class Voice 
{ 
public: 
    double mVoiceValue = 0.0; 
    std::function<double(double)> mTargetFunction; 

    template<typename T, typename F> 
    Voice(T& targetObject, F&& targetFunction) 
     : mTargetFunction(std::bind(targetFunction, targetObject, std::ref(*this), std::placeholders::_1)) { } 
    ~Voice() { } 
}; 

class Osc 
{ 
public: 
    double mOscValue = 1.0; 

    Osc() { } 
    ~Osc() { } 

    double Modulate(Voice &voice, double value) { 
     return mOscValue * voice.mVoiceValue * value; 
    } 
}; 

... 

Osc osc; 
Voice voice1(osc, &Osc::Modulate); 
Voice voice2(osc, &Osc::Modulate); 

voice1.mVoiceValue = 1.0; 
voice2.mVoiceValue = 2.0; 
std::cout << "value: " << voice1.mTargetFunction(10.0) << std::endl; 
std::cout << "value: " << voice2.mTargetFunction(100.0) << std::endl; 

le bit important est l'utilisation de std::ref pour l'argument Voice ici.

Si elle est toujours la fonction de membre Modulate qui va être appelé, le constructeur Voice ne doit pas prendre le pointeur vers la fonction membre comme argument, puis utiliser &T::Modulate dans l'appel à std::bind.

+0

Je ne veux pas utiliser de modèle. – markzzz

+0

@paizza Alors à moins que vous n'utilisiez * toujours * un 'Osc' vous n'avez vraiment pas le choix: soit votre solution soit ma solution avec des templates. Vous n'utiliserez que des objets 'Osc', mais faites une déclaration en avant et codez son utilisation. Créez éventuellement plusieurs surcharges du constructeur 'Voice', chacun prenant un pointeur sur la fonction membre pour chaque objet que vous pourriez utiliser. –

+0

Que voulez-vous dire par "vous utiliserez toujours un Osc"? Je veux utiliser la fonction 'Osc :: Modulate' de' osc', pour chaque voix. Slave a dit "Sachez que vous faites 2 copies de l'objet osc lorsque vous liez." Je ne suis pas sûr de ce qu'il veut dire. Peut-être que c'est lié? – markzzz