2

Short Problem:

How should I check if integers are undefined, just as I can check QStrings for having NULL values?


Backstory:

This is my coding style when I am trying to avoid overloading my functions.

myclass.h

public:
    QString string();          // Return private member variables
    int integer();

    void setString(QString s); // Set private member variables
    void setInteger(int i);

signals:
    void stringChanged();      // Signal that member variable has been changed
    void integerChanged();

protected:
    void myFunction();         // Internal functions
    void resetMemberVariables();

private:
    QString m_String;          // Private member variables
    int m_Integer;

myclass.cpp

QString MyClass::string()
{
    return m_Integer;
}
int MyClass::integer()
{
    return m_Integer;
}

void MyClass::setString(QString s)
{
    m_String = s;
    emit stringChanged();
}
void MyClass::setInteger(int i)
{
    m_Integer = i;
    emit integerChanged();
}

void MyClass::myFunction() 
{
    if (!m_String.isNull()) {}
    if (!m_Int.isNull()) { /* This is obviously impossible */ }
    resetMemberVariables();
}
void MyClass::resetMemberVariables()
{
    if (!m_String.isNull()) { 
        m_String = QString::null;
        emit stringChanged();
    }
    if (!m_Integer.isNull()) {   // Impossible
        m_Integer = NULL;        // Pretty sure this is wrong
        emit integerChanged();
    }
}

TLDR:

Instead of using parameters in functions, I let the user set member variables, and have code execute depending whether or not that member variable has been defined. At the end, I reset all member variables to a NULL value.


From what I understand, int can not have a NULL value because every memory space can be interpreted as an integer. (Please correct me if this is wrong.)

So how should I check whether my int variables have been set?

  • Should I reserve a dummy number?
  • Should I pair it with a bool?
  • Maybe I should make a QPair<int,bool>, the bool toggling its defined or undefined state?
  • 1
    I would go for a dummy number (e.g., if the int's allowed range of values is just positive numbers, I would initialise it to -1), or setting some boolean flag when the initialisation takes place, and checking the flag instead. – ACEG Aug 9 '16 at 8:12
4

The best solution would be to avoid the possibility to ever have an uninitialized integer, by passing the value with the constructor. This way the user of your class is forced to pass a value if he wants to create an instance of your class. If you assume the user will not pass an undefined int, the requirement to check this dissapears.

Of course it can be so that the value of the int cannot be provided untill after instanciation. If this is the case you can fall back to the default value approach, but you should definitely try your best to avoid that if possible.

2

I can think of three possible solutions:

Special Number:
Assign a special number such as -1, or the max number allowable from something like std::numeric_limits<int>::max() or the like, which you can guarantee the number should never be set to ordinarily.

Pointer to int:
Not very intuitive but it gets the job done. Use NULL / nullptr just the same as you would a string. There's no reason why you can't use a pointer for the int as well. This also moves the memory from the stack to the heap, which may be undesirable (though again, the string you're using is on the heap already, so does that matter?)

Separate variable:
Also not very attractive, as it means you need to always edit two variables together. But you could use a Boolean or the like to track if the number has been set. It also adds to memory, which would be trivial really, but could be an issue. If you had a lot of ints you wanted to check in this way, it could become quite bloated code.

Wrapper Class:
You could wrap the int into its own class and use any of the three above methods to check if it is valid, with getters and setters and a simple method to check if the variable is currently valid.


My personal recommendation is to use a wrapper class that uses a pointer. That way you get just the int, no off-limit numbers and it should be easy to read.

  • You can use boost::optional as the wrapper class, or if your compiler is really new, std::optional. – Sebastian Redl Sep 3 '16 at 11:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.