How to use a member variable as a default argument in C++?

C++ObjectDefaultArguments

C++ Problem Overview


I want to make an argument for one of the member functions optional. When no argument is provided, it would use an member variable.

However, when I tried to compile it it shows "error: invalid use of non-static data member 'Object::initPos'"

Just to isolate the problem, I tried defaulting an int type and it compiled fine. I wonder what is the problem with my code and how I could use a member function as default value.

Thank you for your help!

Object.h

class Object
{
    public:
       ...
       void MoveTo(double speed, Point position);

    protected:
       Point initPos; 
       Point currPos;

};

Object.c

void Object::MoveTo(double speed, Point position = initPos)
{
    currPos = postion;
}

Point.h

class Point
{
    ...

    private:
       double x;
       double y;
       double z; 
};

C++ Solutions


Solution 1 - C++

Default argument expressions for a member function can only depend on things that are in class or global scope. The default argument also has to be specified in the method's declaration (i.e. in the header file).

To get around this, you need 2 overloads of your MoveTo method. One that takes 1 argument, and another that takes 2 arguments. The method taking 1 argument calls the other method, passing along the value that you consider as the default.

void Object::MoveTo(double speed)
{
    MoveTo(speed, initPos);
}

void Object::MoveTo(double speed, Point position)
{
    // Everything is done here.
}

Note that when you make MoveTo(double) call MoveTo(double, Point), it allows you to write the implementation of MoveTo only once, thereby respecting the DRY principle.

Solution 2 - C++

Default values are not part of the prototype, i.e. they're resolved by the caller, not by the function itself. So firstly, they have to be visible to the caller. Secondly, they cannot access protected members of the class. (I'm pretty sure you can't even use public members as defaults, but I'm too tired to check.)

To solve the problem, use chained overloads as suggested in other answers.

Solution 3 - C++

You can overload your function member like that:

void Object::MoveTo(double speed, Point position) {
   ....
}

void Object::MoveTo(double speed) {
   Point position = this->initPos;

   MoveTo(speed, position);
}

Solution 4 - C++

Besides overloading, another approach is passing an invalid value as the default value. Then check it inside your function.

void Object::MoveTo(double speed, Point position = InvalidPosition) {
   position = (position != InvalidPosition) ? position : initPos;
   ...
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiontuzzerView Question on Stackoverflow
Solution 1 - C++Emile CormierView Answer on Stackoverflow
Solution 2 - C++Oliver CharlesworthView Answer on Stackoverflow
Solution 3 - C++damsonView Answer on Stackoverflow
Solution 4 - C++DAGView Answer on Stackoverflow