Неоднозначные перегруженные функции — как и почему?

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

static __declspec(dllexport) void PackBits(void *dstBuffer, unsigned long long data, unsigned int &offsetBits, const unsigned int numBits);
static __declspec(dllexport) void PackBits(void *dstBuffer, bool data, unsigned int &offsetBits, const unsigned int numBits);
static __declspec(dllexport) void PackBits(void *dstBuffer, float data, unsigned int &offsetBits, const unsigned int numBits);
static __declspec(dllexport) void PackBits(void *dstBuffer, double data, unsigned int &offsetBits, const unsigned int numBits);

Я пытаюсь сделать следующий вызов из другого объекта, включающего «BitPacker.h»:

void Date::ReflectToBitBuffer(void)
{
    unsigned int offsetBits = 0;
    BitPacker::PackBits(m_packedBuffer, m_year, offsetBits, YR_BITS);
    BitPacker::PackBits(m_packedBuffer, m_month, offsetBits, MO_BITS);
    BitPacker::PackBits(m_packedBuffer, m_day, offsetBits, DY_BITS);
}

"m_year", m_month" и "m_day" являются переменными-членами типа int. Однако при попытке компиляции я получаю следующие ошибки:

error C2668: 'BitPacker::PackBits' : ambiguous call to overloaded function
could be 'void BitPacker::PackBits(void *,double,unsigned int &,const unsigned int)'
or 'void BitPacker::PackBits(void *,float,unsigned int &,const unsigned int)'
or 'void BitPacker::PackBits(void *,bool,unsigned int &,const unsigned int)'
or 'void BitPacker::PackBits(void *,unsigned __int64,unsigned int &,const unsigned int)'
while trying to match the argument list '(char *, int, unsigned int, )'

Итак, я написал тестовое решение со следующим main.cpp для проверки перегрузок, и то, что у меня есть ниже, компилируется нормально:

void OverloadTest(float f);
void OverloadTest(int n, int &numbits);
void OverloadTest(double d);
void OverloadTest(char c, int &numbits);
void OverloadTest(long long l, int &numbits);
void OverloadTest(long long *l);
void OverloadTest(bool b);

int main(int argc, int *argv)
{
    int myInt = 77;
    bool myBool = true;
    float myFloat = 3.14159f;
    double myDouble = 1.57;
    long long myLongLong = 12345;
    long long *ptrLongLong = NULL;
    char myChar = 'q';
    int myNumBits = 10;

    OverloadTest(myInt, myNumBits);
    OverloadTest(myFloat);
    OverloadTest(myDouble);
    OverloadTest(myLongLong, myNumBits);
    OverloadTest(ptrLongLong);
    OverloadTest(myChar, myNumBits);
    OverloadTest(myBool);

    return 0;
}

void OverloadTest(float _f) { int x = 0; }
void OverloadTest(int _n, int &_numbits) { int x = 0; }
void OverloadTest(double _d) { int x = 0; }
void OverloadTest(char _c, int &_numbits) { int x = 0; }
void OverloadTest(long long _l, int &_numbits) { int x = 0; }
void OverloadTest(long long *_l) { int x = 0; }
void OverloadTest(bool b) { int x = 0; }

Я даже попытался упростить:

void Date::ReflectToBitBuffer(void)
{
    unsigned int offsetBits = 0;
    unsigned int testVar2 = 12;
    unsigned int testVar1 = 1977;

    BitPacker::PackBits(m_packedBuffer, testVar1, offsetBits, testVar2);
}

И я все еще понимаю двусмысленность. Однако если я использую поплавок, я этого не делаю. На данный момент я совершенно не понимаю, почему мой тестовый сценарий не выдает эту ошибку. Может ли кто-нибудь пролить свет на то, в чем проблема, потому что сигнатуры прототипов функций в первом примере кода кажутся мне достаточно разными, чтобы их можно было скомпилировать.


person Ryan Van Dyke    schedule 06.04.2012    source источник
comment
Я не вижу функции PackBits, которая принимает int в качестве второго параметра, что, похоже, именно то, о чем говорит вам сообщение об ошибке. Int нужно было бы преобразовать в другой тип, но компилятор не знает, какой именно вам нужен.   -  person Retired Ninja    schedule 06.04.2012
comment
Передайте unsigned int в тестовом сценарии.   -  person Jesse Good    schedule 06.04.2012


Ответы (1)


Похоже, что «int» можно привести ко всем 4 типам вашей перегруженной функции, и ни один из них точно не соответствует вашему вызову. Может быть, это проблема. Попробуйте сделать так, чтобы ваш вызов точно соответствовал определению функции или сделал версию int для вашего вызова?

person xxbidiao    schedule 06.04.2012
comment
Соглашение о вызовах C не делает различий между подписанными и неподписанными типами или просто дает предупреждение, как я понимаю. Но да, я пробовал это с беззнаковым целым числом и целым числом. Все члены моего класса даты на самом деле являются целыми числами, и когда это не сработало, я попробовал беззнаковое целое число. - person Ryan Van Dyke; 06.04.2012
comment
На самом деле прототип был unsigned long long. Я думал, что передача unsigned int функции, принимающей unsigned long long, автоматически приведет к его повышению? Я пробовал unsigned long long, и это сработало. Спасибо, парни. - person Ryan Van Dyke; 06.04.2012
comment
Похоже, моя основная проблема заключалась в том, что статические функции более строги со своими параметрами, чем нестатические функции? Статические функции, похоже, способны различать даже подписанные и неподписанные типы... - person Ryan Van Dyke; 06.04.2012
comment
Я предполагаю, что вы говорите о функциях OverloadTest по сравнению с функциями PackBits? Статика не имеет ничего общего с тем, почему один работает, а другой нет. Все вызовы OverloadTest были точными совпадениями, а проблема PackBits заключается в том, что не было точного совпадения и ни одного неявного преобразования, которое было бы лучше, чем любое другое возможное неявное преобразование. - person Retired Ninja; 06.04.2012
comment
Ах, я думаю, что я понимаю это сейчас. Итак, если у меня есть только 1 функция, которая принимает целое число, она будет принимать как целое число, так и целое число без знака, если я не создам две функции, которые принимают оба. Думаю, тут я запутался. Спасибо за вашу помощь! - person Ryan Van Dyke; 06.04.2012