конструктор перегрузки c ++ с int и char * - PullRequest
5 голосов
/ 31 марта 2011

Я пытаюсь перегрузить конструктор с int и char *.Тогда есть неоднозначность в колле с 0.Есть ли какое-либо решение / решение для этого?

CBigInt (unsigned int);
CBigInt (const char *);

Проблема на линии с 0:

CBigInt a;
// some more code
 a *= 0; 

Спасибо за ответ.

Ответы [ 4 ]

10 голосов
/ 31 марта 2011

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

CBigInt (unsigned int);
explicit CBigInt (const char *);
6 голосов
/ 31 марта 2011

Вы можете использовать "явное" ключевое слово:

explicit CBigInt(const char *);

Используя это, вы должны явно привести аргумент к const char *, в противном случае будет выполнен CBigInt (без знака).

2 голосов
/ 31 марта 2011

«Явный» подход работает, но, возможно, не будет интуитивно понятным для поддержки разработчиков в будущем. Для подобных случаев в предыдущих проектах, над которыми я работал, мы использовали статические фабричные методы. У нас был бы закрытый конструктор по умолчанию, и мы явно инициализировали элементы в статических фабриках. Что-то вроде:

class CBigInt {
public:
...
static CBigInt fromUInt(unsigned int i) { 
    CBigInt result; 
    result.value=i; 
    return result; 
}
static CBigInt fromCharPtr(const char* c) { 
    CBigInt result; 
    result.value=parse(c); 
    return result; 
}
...
private:
CBigInt () {}
/*some internal type here*/ value; 
};

Этот подход устраняет любую неопределенность не только для компилятора, но и для того, кто будет поддерживать ваш код позже.

1 голос
/ 31 марта 2011

В этом случае я бы также рекомендовал конструктор explicit, потому что я думаю, что произвольная строка (которую принимает ваш конструктор) не моделирует число (которое моделирует ваш CBigInt класс). Для таких случаев и предназначен explicit.

Однако это не будет работать в случаях, когда используется прямая инициализация

struct A {
  CBigInt n;
  A():n(0) { } // ambiguity again
};

Как правило, explicit не следует использовать для устранения внутренних неопределенностей. Его следует просто использовать для запрета преобразования из одного типа в другой, но не для предпочтения другого конструктора по сравнению с конструктором explicit. Фактически, новые унифицированные инициализации C ++ 0x не игнорируют конструкторы explicit в контексте инициализации копирования:

CBigInt f() {
  return { 0 }; // still ambiguous
}

CBigInt b = { 0 }; // still ambiguous

Правила для равномерной инициализации таковы: оба конструктора рассматриваются, но если выбран явный конструктор, инициализация некорректна.

Буквально 0 является int. Предполагая, что вы хотите принимать все целочисленные типы, вам нужно как минимум добавить int принимающий конструктор. Вам не нужно добавлять перегрузки для целочисленных типов, меньших int, потому что эти типы предпочитают int другим целочисленным преобразованиям или указателям. Предполагая, что у вас есть перегрузка int, вам также необходимо добавить перегрузки для оставшихся целочисленных типов и, если доступно, и использовать его, long long и unsigned long long. Двусмысленности больше не возникнет:

CBigInt (int);
CBigInt (unsigned int);
CBigInt (long);
CBigInt (unsigned long);
// CBigInt (long long);
// CBigInt (unsigned long long);
explicit CBigInt (const char *);
...