modifying private members across classes and setter/getter friendzy

Hi all,
I have a project in which I have the following class tree with the main state machine class englobing everything. Shown is basically my classes to operate a TFT screen and a speaker.

|------- Sound ------- Speaker hardware IF
FSM
| ------ UI ------ Screen IF




Now, I want the user to be able to configure some settings that will show onscreen, notably sound volume. The sound volume variable must therefore be shared between the speaker hardware interface class and the screen interface class. It feels very heavy to do a series of setters and getters to move the variable up 2 levels to the state machine and then 2 levels down. Imagine with all the other settings that would come from different classes...

So I have 2 options in mind, but I am not sure that is the way a pro would do it. I was thinking about doing setters and getters but for a pointer to the private sound volume variable and bring it all the way up to the screen IF. this way, the screen would show the value straight from the class member value and edit it directly.
The other idea I had was to store another volume variable inside of the screen class, and then when it is changed, use a settingsChanged(int newVolumeLevel) callback function that would pass the volume value as argument and set the sound interface variable to the same value (that callback could be a pointer to a function belonging to the state machine, and that function when called from the pointer would just do something like speaker.setvolume(newVolumeLevel). Since in this case there are two volume variables, I am worried it may cause aliasing problems.

Anyway, I was wondering if any of you knew what is a common and robust way to modify private members in such convoluted class trees?
Thanks a alot for your help!
Last edited on
Perhaps create a class which would establish and maintain the invariants for sound volume, and with that we can expose the encapsulated sound volume as a public member object of, say, the speaker class.

Something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <algorithm>
#include <iostream>

struct sound_volume // logically an integer in [0,99]
{
    // constructor establishes the invariant (silently corrects invalid values)
    sound_volume( int vol = 49 ) : volume( std::clamp( vol, 0, 99 ) ) {}

    operator int() const noexcept { return volume ; }

    private: int volume ; // 0-99
};

int main() // usage example
{
    sound_volume vol ;
    vol = 12345 ; // clamped to 99
    std::cout << vol << '\n' ; // 99
    vol = -34 ; // clamped to 0
    std::cout << vol << '\n' ; // 0
    vol = 72 ; // ok
    std::cout << vol << '\n' ; // 72
}

Good idea!

although if the user changes the volume, the screen object still needs to tell the UI object, which will tell the state machine object, which will tell the sound_volume object via set/get? or you would use a pointer in the screen object that can directly change the volume memebr of the sound_volume object? Thanks!
> or you would use a pointer in the screen object
> that can directly change the volume memebr of the sound_volume object?

Since (I think) it can't be a null pointer, a reference may be more appropriate.
Topic archived. No new replies allowed.