在C++中管理隐式类型转换
我正在处理最近邻查询的代码。有两个简单的想法构成了用户如何在搜索中查询数据的基础:在C++中管理隐式类型转换
- 最靠近的N个点指向空间中的给定点。
- 给定距离内的所有点。
在我的代码中,点被放入一个PointList中,而PointList是一个容器,用于跟踪在搜索中找到的点。
现在我PointList对象一个构造函数:
PointList(unsigned int maxvals); // #1
接下来的两个,我想补充的构造是这些:
PointList(float maxdist); // #2
PointList(unsigned int maxvals, float maxdist); // #3
我的问题是:我怎么保证我的用户和C++编译器将为PointList生成正确的 构造函数并区分构造函数1和2? 我是否应该实现#3并提供定义maxval和maxdist的任意大 值的常量?另一种选择可能是编写另一个轻量级对象系统来控制将列表添加到列表中的逻辑,但这对于这样一个简单的想法感觉像是矫枉过正。
我真的试图使这个透明为我的用户,谁是谁大多已经学会了C++有时没有接受正规教育的好处科学家。谢谢!
重载决策发生在两大类,其中可以非常粗略地归纳到
- 推广:这是类型转换小于
int
到int
或unsigned int
,取决于int
是否可以将所有源类型的值。 - 转换:这是从任何整数类型转换为另一种整数类型。
类似,转换为浮点类型发生在两个类别
- 推广:这是从
float
到double
- 转换在转换:这是从任何浮点类型到另一种的转换浮动点类型
并且存在从整数到浮点或返回的转换。这被列为转换,而不是升级。晋升排名比转换好,只要需要晋升,那么这种情况会更受欢迎。因此,您可以使用以下构造函数
PointList(int maxVals);
PointList(unsigned int maxVals);
PointList(long maxVals);
PointList(unsigned long maxVals);
PointList(double maxDist);
PointList(long double maxDist);
对于任何整数类型,应该选择第一组构造函数。对于任何浮点类型,这应该选择第二组构造函数。例如,如果您通过int
,则原来的两个构造函数很容易造成float
和unsigned int
之间的不明确。对于另外两个参数构造函数,如果你愿意,你可以使用你的解决方案。
也就是说,我也会使用一个工厂函数,因为我认为这个参数的意义是相当脆弱的。大多数人会预期以下结果相等:
PointList p(floor(1.5));
PointList u((int)1.5);
但是它会导致不同的状态。
呼叫PointList(10),用于所述第一和PointList(10F)用于第二。
对于第二个,你也可以使用10.0。
为什么不使用工厂方法代替构造函数?工厂方法具有可定制名称的优点。
static PointList createNearestValues(unsigned int maxvals) {}
static PointList createByDistance(float maxdist) {}
如果构造#1和#2都存在,如果将值是浮动或int和无转换应该进行正确的构造函数将被调用。所以只要确保你使用的数字类型可以显式调用(即1f和1)即可。 构造函数#3似乎不是一个很好的选择,因为它不是真的必要,只会混淆用户的代码。 如果您需要默认值,无论是数量,你可以使用
PointList(int max, float max=VALUE)
和
PointList(float max, int max=VALUE)
还是那句话:这似乎在代码的可读性方面做更多的伤害,然后代码。
我肯定会用显式构造函数。在示例中,无符号整数不会隐式转换。
class A
{
public:
explicit A(float f){}
explicit A(int i){}
};
void test(){
unsigned int uinteger(0);
A a1(uinteger); //Fails, does not allow implicit conversions
A a2((float)uinteger); //OK, explicit conversion
float f(0.0);
A a3(f); //OK
int integer(0);
A a4(integer); //OK
}
的错误消息是很容易理解:
: error C2668: 'A::A' : ambiguous call to overloaded function
: could be 'A::A(int)'
: or 'A::A(float)'
这绝对是一个可能性,但我的用户可能不理解的差异。他们中的一些人可能并不熟悉编译器区分浮点数和未签名整数的方式。 – 2009-06-26 20:28:27