PDA

View Full Version : Are global variables evil?



Wonk0
1st February 2011, 13:31
Hi there!

I'm new to Qt programming. Well, I already used Qt 3 before, but I only made modifications to an existing application, the main design came from someone else. Now I'm going to learn Qt4. And this forum seems to be an excellent resource. I'm only sorry that for now I only have questions and cannot help others here. So, here comes a big thank you for those who do.

There is one basic question have, about global variables. They seem to be considered bad programming style, and normally I also try to avoid them. On the other hand, the old Qt3 projects I was also working on always had a single global variable, a pointer to the main object. Whatever subroutine I was in, I always could acess the data I needed.

Example: My little Qt4 testing project draws some geomtric figure (e.g. a circle), and there is a slider to change the radius. Simple, even for my standards :) Now I added an input field and a dial as alternative ways to set the radius. So when the slider is changed, the other two widgets should change accordingly.

I guess I should connect those widgets, so when the slider is changed, the other two widgets get the signal to change accordingly. But how do I prevent them to:

Send signals back to the slider widget, avoiding an infinite cascade of events
Prevent the other widgets from also updating the draw area again

And how do I get the current radius in other parts of my application? I solved this by simply creating my global pointer to the main object, which has an int m_radius that gets set in the event handlers (and according getRadius() and setRadius() methods). But this does not seem to be the recommended way of doing it.

Well, how do you do this?


Thanks for reading, and sorry if these questions are too stupid,
Wonk0

high_flyer
1st February 2011, 14:32
There is one basic question have, about global variables. They seem to be considered bad programming style, and normally I also try to avoid them. On the other hand, the old Qt3 projects I was also working on always had a single global variable, a pointer to the main object
Global variables are a language feature, they are not evil if you use them when their use makes sense.
C++ inherited this feature from C.
In C, there are no classes, so globals where needed.
In C++, you have classes, and they have members, which means, that if you do your encapsulation right, you wont come to need globals.
But sometimes (seldom) it can come to it that a global is needed.

But how do I prevent them to:

1. Send signals back to the slider widget, avoiding an infinite cascade of events
2. Prevent the other widgets from also updating the draw area again

Have a look at the 'tracking (http://doc.trolltech.com/4.7/qabstractslider.html#tracking-prop)' property.

squidge
1st February 2011, 17:32
I agree with high_flyer, global variables are not evil, but when possible, use encapsulation.

The golden rule in C is that a variable should not be a global if it only needs to be accessed by functions in the same file (this becomes a 'must' in many coding policies used by companies). If a variable only needs to be read, it should be file-local and a function provided to provide the contents.

In C++ you have class encapsulation instead of file encapsulation. Only use globals if it makes sense to do so.

Wonk0
2nd February 2011, 20:11
Global variables are a language feature, they are not evil if you use them when their use makes sense.
C++ inherited this feature from C.
In C, there are no classes, so globals where needed.
In C++, you have classes, and they have members, which means, that if you do your encapsulation right, you wont come to need globals.
But sometimes (seldom) it can come to it that a global is needed.
Okay, advice taken. I will try to do it without globals now.

I started to use them when I had trouble to access my main widget (QTest) in a little test project I made with Qt Creator. It uses a custom widget class for drawing that does not know about my main class.

Now I added a member variable containing a pointer to my main widget, and set it like this in the constructor:
m_QTest = (QTest*) parent->parent();

What I did not like about this is that when I move that widget deeper in the hierarchy, I have to change this. So the widget needs to know where it is, and cannot be treated as a black box like before.


Have a look at the 'tracking (http://doc.trolltech.com/4.7/qabstractslider.html#tracking-prop)' property.
Hmm, that does seem to toggle whether I get events while dragging as slider, or only after it has been moved. My problem is another one:

I have a slider and a text input field, both are methods to specify the radius of the object I draw. There is also an update button to force a redraw. So, I made connections from the slider and the text input field to the update button, and now my object gets redrawn when I press the update button, move the slider or edit the text input field. But how do I make sure the slider and the input field always show the same value? I could set their values in the onUpdateButton_clicked() event, but this would generate additional events:

change value in input field
m_radius gets set in on_radiusLineEdit_textChanged()
signal is sent to onUpdateButton_clicked(), which updates the draw area, and sets the values of the text input field (unnecessary, but not harmful) and the slider
this generates an event for the slider that has changed
things are drawn again, and the value in the text field is changed a little, because the slider has a resolution of 1-100, while the input field's value is donverted into a a floating point with more precision
and again the changed text field will generate an event

How do I avoid this? Simply disable event processing somehow, update the values in all widgets, and enable events again? I am probably overlooking something simple here.