Как сделать опорный параметр в функции необязательным (необязательный буфер) - PullRequest
2 голосов
/ 19 июня 2011

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

Однако это означает, что два параметра buff должны быть ссылками и должны присутствовать при каждом вызове функции, и я не знаю ни одного способа сделать ссылку по умолчанию. Как я могу это сделать?

Вот фактическая функция:

bool CheckCollision(T* obj1, T* obj2, float& CollBuff1= new float, float& CollBuff2= new float);

Я пытался установить значение по умолчанию с «новым», но это не сработало.

Ответы [ 5 ]

8 голосов
/ 19 июня 2011

Вы можете перегрузить функцию. Просто определите вторую функцию-обёртку так:

bool CheckCollision(T *obj1, T *obj2)
{
    float dummy1, dummy2;
    return CheckCollision(obj1, obj2, dummy1, dummy2);
}

И, если хотите, укажите вторую, если указан только один float.

4 голосов
/ 19 июня 2011

С Повышение. Опционально , без указателей и без перегрузки шаблонов:

bool CheckCollision(
    T* obj1, T* obj2,
    boost::optional<float&> CollBuff1 = boost::optional<float&>(),
    boost::optional<float&> CollBuff2 = boost::optional<float&>()
);

Вы можете проверить, есть ли у вас аргумент, выполнив if (CollBuff1), а затем получить доступ к ссылке с помощью CollBuff1.get() (и другой аналогично, очевидно).

1 голос
/ 19 июня 2011

Основная проблема, с которой вы пытаетесь определить значение по умолчанию для ссылочного параметра, заключается в том, что неконстантная ссылка не может быть связана с временным объектом или литералом.

void foo(float &f = 1.0f) {} // doesn't compile
void foo(const float &f = 1) {} // OK

Фактическиэто законно:

void foo(float &f = *(new float(1))) {}

Но это довольно нежелательно.Код в функции не может сказать, был ли он вызван с параметром по умолчанию или нет, так что вы создали для себя довольно неприятную проблему с обработкой ресурсов: кто собирается delete это плавать, и что будет этот кодделать в случае, когда звонящий что-то пропустил?Перегрузка bdonlan предпочтительна.

1 голос
/ 19 июня 2011

Альтернативный (и очень уродливый) способ сделать это был бы так:

#include <memory>

void test(int a, int& b = *std::auto_ptr<int>(new int())) {
     // ...
}

или в вашем случае

#include <memory>

bool CheckCollision(T* obj1, T* obj2,
    float& CollBuff1= *std::auto_ptr<float>(new float()),
    float& CollBuff2= *std::auto_ptr<float>(new float()));
0 голосов
/ 19 июня 2011

А теперь удаленный (почему?) Ответ от @James McNellis указывает на правильное решение: вы не.

Используйте для этого указатели, поскольку эти буферы, очевидно, являются выходными параметрами (то есть они используются для «возврата» дополнительных значений) и соответственно вызывают его:

bool CheckCollision(T* obj1, T* obj2, float* ColBuf1 = 0, float* ColBuf2 = 0){
  // your code...
  // ...
  // test before assigning:
  if(ColBuf1 != 0)
    *ColBuf1 = /*whatever you have*/;
  // same with ColBuf2
}

float ColBuf1, ColBuf2;
CheckCollision(SomeObjPtr, AnotherObjPtr, &ColBuf1, &ColBuf2);

Или, что еще лучше, перегрузите его:

bool CheckCollision(T* obj1, T* obj2);
bool CheckCollision(T* obj1, T* obj2, float* ColBuf1, float* ColBuf2);

Хотя я все еще использовал бы указатели, чтобы указать, что эти буферы будут заполнены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...