1

Since my last question had too much code in it, I tried to make the simplest example of what I'm trying to do. Take this for example,..

#include <iostream>
using namespace std;

class String
{
    public:
    private:
};

class ClassTwo
{
    public:
        int memberVariable;
    private:
};

class ClassOne
{
    public:
        ClassOne (ClassTwo&, String&);
        ~ClassOne();

    private:
        ClassTwo& classTwoReference;
        String& stringReference;
};

ClassOne::ClassOne (ClassTwo& two, String& string)
    : classTwoReference (two), stringReference (string)
{
    two.memberVariable = 3;
}

ClassOne::~ClassOne()
{
}

int main()
{
    String stringObject;
    ClassTwo classTwoObject;
    ClassOne classOneObject (classTwoObject, stringObject);
}

In JUCE, which is the API I'm using to code a VST Plugin, there is a string class that JUCE names "String". I'm not sure exactly what the constructor does, but you can use something like this to create a String object.

String newString("string");

The ClassTwo in my case, is the AudioProcessor class which has a public member variable that I can access from ClassOne like this.

two.memberVariable = 3;

The ClassOne in my case, is a custom Component(I named it PixelSlider) that I'm using in my GUI. It uses a slider listener to check the status of a slider and modify the member variable in ClassTwo(AudioProcessor). I can do this fine using the method above, but the issue is that I want to create as many ClassOne(PixelSlider) objects as I need. I want to pass them a String object that tells them what member variable of ClassTwo(AudioProcessor) to modify. Logically, this would be done by passing a reference to a String object with the same string value as the name of the ClassTwo member variable. Like this,...

ClassOne::ClassOne (ClassTwo& two, String& string)
        : classTwoReference (two), stringReference (string)
    {
        two.(string) = 3;
    }

This doesn't work in JUCE, but can anybody tell me a way to get this done without having to create a bunch of different classes almost exactly like ClassOne(PixelSlider) that modify different ClassTwo(AudioProcessor) member variables?

  • 3
    _"This obviously doesn't work in JUCE"_ There's nothing obvious about this. Also note, that you're supposed to edit and improve your last question , and not to post another one. – πάντα ῥεῖ Jan 17 '15 at 11:22
  • So you're saying it should work? Also, I deleted my last question. Improving it would be completely changing it, so I just posted a new one and deleted it. – Stevey Yarusinsky Jan 17 '15 at 11:26
  • 1
    I said there's nothing obvious for me why it shouldn't. If it doesn't work for you, you should elaborate what exactly doesn't work. – πάντα ῥεῖ Jan 17 '15 at 11:27
  • the way to do this is to create different classes like ClassOne which change different variable. If not that, then you have to keep some indexing for class members and pass the index of variable you want to modify (Though this looks very ugly) – Pankaj Bansal Jan 17 '15 at 11:29
  • Thanks Pankaj! That was my intuition, but I was hoping there would be a simpler way to do it. By the way, I edited out the "obviously" part since I can't even really explain why it doesn't work. – Stevey Yarusinsky Jan 17 '15 at 11:31
  • Or you can make some mapping from string to a variable in ClassTwo like map["someString"] = two.someVariable. Then pass the string and change it. Again sounds ugly.. – Pankaj Bansal Jan 17 '15 at 11:33
  • 1
    @SteveyYarusinsky You still missed to explain **what** doesn't work. – πάντα ῥεῖ Jan 17 '15 at 11:34
  • @πάνταῥεῖ that won't work. How will you change the variable of two by from string. two.string = 3 does not make any sense I feel as the variable is not string – Pankaj Bansal Jan 17 '15 at 11:35
  • Yeah, I think I'll just have to make some derived classes based off ClassTwo. I prefer not to have it be ugly. And @πάνταῥεῖ, the thing that doesn't work is that "two.(string) = 3;" gives me compile errors. – Stevey Yarusinsky Jan 17 '15 at 11:37
  • There are languages (such as PHP) where you can use a variable to reference another variable, e.g. `$x = 1; $s = 'x'; $$s = 42;` will set `$x` to 42. The term for this is "reflection". If you search for "reflection in C++", you'll find LOTS of questions on this. The short answer is that C and C++ does not have this, there is no way the compiler can translate a runtime generates string to a member field. The language is just meant to do that. There are lots of different ways to achieve something similar, but not EXACTLY that. – Mats Petersson Jan 17 '15 at 11:43
  • I'll try to explain it again, when I create an instance of ClassOne(PixelSlider) in my GUI class, I pass it a reference to a classTwo object(AudioProcessor) and a reference to a string object. Like this "PixelSlider sliderOne (AudioProcessor& p, String& memberOfAudioProcessorThatIWantToModify);" In method of the PixelSlider object, I want a member of the AudioProcessor to be modified, but I want to specify which one I want to modify when I create the PixelSlider object so that I don't have to create a bunch of classes with only a few lines of code that is different. Does that make sense? – Stevey Yarusinsky Jan 17 '15 at 11:44
  • @MatsPetersson, thanks! I figured that might be the case. That's a shame though. I think the best decision would be to create classes that inherit the functions of ClassOne, then override the ones that contain the code I want to change. Would that be a good route to take? – Stevey Yarusinsky Jan 17 '15 at 11:47
  • 1
    There are LOTS of solutions, it really depends on the overall situation. Your example is far too simple/small to clearly see what you are trying to do. The answer posted is ONE of those, but not always the right answer. – Mats Petersson Jan 17 '15 at 11:54
  • Try avoiding `using namespace std;` here is why: http://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice – ilgaar Jan 17 '15 at 13:30
  • Ah, I see, although I'm not using any namespaces in my JUCE code. Thanks for the tip @igaar very helpful! – Stevey Yarusinsky Jan 17 '15 at 19:08

1 Answers1

1

If I understand correctly, you're trying to bind a PixelSlider target to a member of AudioProcessor at runtime, which, as you've discovered, can't be done the way you suggest ( two.(string) = 3 ). One way of achieving this binding would be to use the command pattern (http://sourcemaking.com/design_patterns/command/cpp/2).

AudioProcessor could expose a collection of these command objects for each modifiable property ...

AudioProcessorCommand
AudioProcessor::GetCommandByName(String const& properyName) const
{
   ...
}

... which you can pass to the constructor of PixelSlider. Something along the lines of ...

PixelSlider::PixelSlider(AudioProcessorCommand& command)
: command_{command}
{
  ...
}

When the PixelSlider's value changes you would invoke the command ...

command_(this->value_);
gmbeard
  • 674
  • 6
  • 19