c++ overload constructor with int and char*
I try to overload constructor with int
and char *
. Then there is ambiguity in call with 0
. Is there any workaround/solution for this?
CBigInt (unsigned int);
CBigInt (const char *);
开发者_Go百科The problem is on the line with 0
:
CBigInt a;
// some more code
a *= 0;
Thanks for answering.
Make one of the constructors explicit. It will then only be used when passed type exactly matches.
CBigInt (unsigned int);
explicit CBigInt (const char *);
You could use the "explicit" keyword:
explicit CBigInt(const char *);
Using this, you must explicitly cast the argument to a const char *, otherwise CBigInt(unsigned) will be executed.
The 'explicit' approach works, but may not be intuitive for supporting developers in the future. For cases like these, in previous projects I've worked on, we used static factory methods. We would have a private default constructor and explicitly initialize the members in the static factories. Something like:
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;
};
This approach removes any ambiguity not only for the compiler, but also for the one who will support your code later.
In this case I would also recommend an explicit
constructor, because I think that an arbitrary string (which your constructor takes) does not model a number (which your CBigInt
class models). Such cases are what explicit
was designed for.
However, this will not work for cases where direct initialization is used
struct A {
CBigInt n;
A():n(0) { } // ambiguity again
};
In general, explicit
should not be used to resolve internal ambiguities. It should merely be used to forbid the conversion from one type to the other, but not to prefer another constructor over the explicit
constructor. In fact, the new C++0x uniform initializations will not ignore explicit
constructors in a copy initialization context:
CBigInt f() {
return { 0 }; // still ambiguous
}
CBigInt b = { 0 }; // still ambiguous
The rules for uniform initialization is: Both constructors are considered, but if an explicit constructor is chosen, initialization is ill-formed.
The literal 0
is an int
. Assuming you want to be able to accept all integer types, you need to at least add an int
taking constructor. You don't need to add overloads for integer types smaller than int
, because those types prefer int
over other integer conversions or pointers. Assuming you have an int
overload you also need to add overloads for the remaining integer types and, if available and you use it, long long
and unsigned long long
. Ambiguities will then not arise anymore:
CBigInt (int);
CBigInt (unsigned int);
CBigInt (long);
CBigInt (unsigned long);
// CBigInt (long long);
// CBigInt (unsigned long long);
explicit CBigInt (const char *);
精彩评论