Как использовать переменную-член в качестве аргумента по умолчанию в C++?

Я хочу сделать аргумент для одной из функций-членов необязательным. Когда аргумент не предоставлен, он будет использовать переменную-член.

Тем не менее, когда я пытался скомпилировать его, он показывает "ошибка: недопустимое использование нестатического члена данных" Object::initPos ""

Просто, чтобы изолировать проблему, я попытался по умолчанию использовать тип int, и он скомпилировался нормально. Интересно, в чем проблема с моим кодом и как я могу использовать функцию-член в качестве значения по умолчанию.

Спасибо за помощь!

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; 
};

3 ответа

Решение

Выражения аргументов по умолчанию для функции-члена могут зависеть только от того, что находится в классе или глобальной области видимости. Аргумент по умолчанию также должен быть указан в объявлении метода (то есть в заголовочном файле).

Чтобы обойти это, вам нужно 2 перегрузки вашего метода MoveTo. Один принимает 1 аргумент, а другой - 2 аргумента. Метод, принимающий 1 аргумент, вызывает другой метод, передавая значение, которое вы считаете значением по умолчанию.

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

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

Обратите внимание, что когда вы делаете MoveTo(double) вызов MoveTo(double, Point), это позволяет вам написать реализацию MoveTo только один раз, тем самым соблюдая принцип СУХОГО.

Значения по умолчанию не являются частью прототипа, то есть они разрешаются вызывающей стороной, а не самой функцией. Итак, во-первых, они должны быть видны звонящему. Во-вторых, они не могут получить доступ к защищенным членам класса. (Я почти уверен, что вы не можете использовать публичных участников по умолчанию, но я слишком устал, чтобы проверять.)

Чтобы решить проблему, используйте цепные перегрузки, как предложено в других ответах.

Вы можете перегрузить свой член функции следующим образом:

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

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

   MoveTo(speed, position);
}

Помимо перегрузки, существует другой подход - передача недопустимого значения в качестве значения по умолчанию. Затем проверьте это внутри своей функции.

void Object::MoveTo(double speed, Point position = InvalidPosition) {
   position = (position != InvalidPosition) ? position : initPos;
   ...
}
Другие вопросы по тегам