0

У меня есть класс с несколькими конструкторами и перегруженных операторов:C++ Неоднозначный вызов конструктора

class Utf8String 
{ 
public: 

    Utf8String(); 

    explicit Utf8String(const char * sStr); 

    Utf8String(const char * sStrBeg, const char * sStrEnd); 

    Utf8String(const char * sStr, uint32_t nCpCount); 

    explicit Utf8String(const Utf8String & sStr); 

    explicit Utf8String(const Utf8String & sStr, uint32_t nStart = 0, uint32_t nCpCount = UINT32_MAX); 

    Utf8String(uint32_t nCpCount, uchar32_t cCodePoint); 

    explicit Utf8String(long int iVal); 

    explicit Utf8String(double fVal); 

    // More stuff 

    inline Utf8String operator + (const char * sStr) const 
    { 
     Utf8String sRes(*this); // ERROR 
     return sRes += sStr; 
    } 

    inline operator const char *() const; 

    inline operator char *(); 

    inline operator long int() const; 

    inline operator double() const; 
}; 

По какой-то причине, я получаю сообщение об ошибке:

Error 3 error C2668: 'core::Utf8String::Utf8String' : ambiguous call to overloaded function c:\xxx\utf8string.h 280 

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

У вас есть идея? Спасибо.

+1

Какая строка 'utf8string.h 280'? – timrau

+0

Тот, у кого комментарий '// ERROR', а также единственный код для реализации. – Virus721

+0

Вы получаете ошибку, потому что два конструктора соответствуют вызову. 'Utf8String (const Utf8String & sStr)' и 'Utf8String (const Utf8String & sStr, uint32_t nStart = 0, uint32_t nCpCount = UINT32_MAX)' оба являются хорошими кандидатами. Это запрещено. Вам нужно определить один конструктор копирования, а не два. –

ответ

3

Эти две функции:

explicit Utf8String(const Utf8String & sStr); 

explicit Utf8String(const Utf8String & sStr, uint32_t nStart = 0, uint32_t nCpCount = UINT32_MAX); 

не должны существовать одновременно. Они вызывают проблему.

Поскольку остальные аргументы второго конструктора имеет по умолчанию значения, они будут вызывать неоднозначную ошибку, если вы передаете только один аргумент, как показано ниже:

Utf8String s = get_utfString(); 

Utf8String s1(s); //which above constructor should be called? 

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

Кроме того, эти конструкторы являются копировальными конструкторами, поэтому explicit не имеет большого смысла. Вы должны использовать explicit, чтобы избежать неявных версии от одного типа X до другого типа Y. В этом случае исключение неявного преобразования из Utf8String const& в Utf8String не имеет смысла, поскольку такое преобразование действительно не вызовет проблемы (если это произойдет, то проблема, вероятно, будет в других частях вашего кода).

+0

Спасибо за помощь. Я не уверен, чтобы понять, почему явное не имеет смысла в конструкторе копирования. Не могли бы вы объяснить, пожалуйста? – Virus721

+0

@ Virus721: добавлено объяснение этого. – Nawaz

+0

Хорошо. И у меня был бы другой вопрос такого же типа, если вы хотите. Представьте, что у меня есть метод 'Foo (const Utf8String &)' и метод 'Foo (const char *)'. Поскольку Utf8String может быть преобразован в 'const Utf8String &' и 'const char *', я не собираюсь получать проблемы с этим методом Foo? Не могу ли я использовать явные методы тоже? Спасибо. – Virus721

1

Ваших следующие два конструкторы могут одновременно служить в качестве конструктора копирования:

explicit Utf8String(const Utf8String & sStr); 
explicit Utf8String(const Utf8String & sStr, uint32_t nStart = 0, uint32_t nCpCount = UINT32_MAX); 

каждый из них соответствует Utf8String(const Utf8String & sStr) подписи. Это то, что компилятор не любит.

Вы должны действительно подумать, какой из двух конструкторов вы хотите использовать в качестве конструктора копирования. Если это первый, то снимите значение по умолчанию для nStart во втором конструкторе. Если он второй, то полностью оставьте первый конструктор.

На самом деле, я предполагаю, что ваш второй конструктор просто принимает подстроку и поэтому вызвал без nStart и nCpCount аргументы будут работать точно так же, как ожидается, будет работать конструктор копирования. Таким образом, самый простой способ - просто отбросить первый конструктор этой пары.

Однако это может привести к некоторым (главным образом, проблемам с перфомансом) в зависимости от вашего представления Utf8String, так что вам решать.

+0

Я просто удалю значение по умолчанию для nStart, чтобы сохранить два отдельных конструктора по соображениям производительности, как вы догадались. Спасибо за вашу помощь. – Virus721