C++ 在C+中管理隐式类型转换+;

C++ 在C+中管理隐式类型转换+;,c++,c,type-conversion,C++,C,Type Conversion,我正在编写执行最近邻查询的代码。用户如何在搜索中查询数据,有两个简单的想法: 距离空间中给定点最近的N个点 给定距离内的所有点 在我的代码中,点被放入点列表中,点列表是一个容器,负责跟踪在搜索中找到的点 现在,我的PointList对象有一个构造函数: PointList( unsigned int maxvals ); // #1 接下来我要添加的两个构造函数是: PointList( float maxdist ); // #2 PointList( unsigned int maxv

我正在编写执行最近邻查询的代码。用户如何在搜索中查询数据,有两个简单的想法:

  • 距离空间中给定点最近的N个点
  • 给定距离内的所有点
在我的代码中,点被放入点列表中,点列表是一个容器,负责跟踪在搜索中找到的点

现在,我的PointList对象有一个构造函数:

PointList( unsigned int maxvals ); // #1
接下来我要添加的两个构造函数是:

PointList( float maxdist ); // #2
PointList( unsigned int maxvals, float maxdist ); // #3
我的问题是:如何确保我的用户和C++编译器将生成正确的 点列表的构造函数,并区分构造函数1和构造函数2? 我是否应该实现#3并提供定义任意大值的常量 maxvals和maxdist的值?另一种选择可能是编写另一个轻量级对象系统来控制向列表中添加点的逻辑,但对于这样一个简单的想法来说,这感觉有些过头了

我真的想让我的用户透明,他们大多是科学家,他们有时学习C++而没有正规教育的好处。谢谢

第一个调用点列表(10),第二个调用点列表(10f)


第二,您也可以使用10.0。

为什么不使用工厂方法而不是构造函数?工厂方法具有可自定义名称的优势


static PointList createNearestValues(unsigned int maxvals) {}
static PointList createByDistance(float maxdist) {}
如果存在构造函数#1和#2,则如果插入的值为float或int且不应进行转换,则将调用正确的构造函数。因此,只需确保将用于调用的数字类型显式化(即1f和1)。 构造函数#3似乎不是一个很好的选项,因为它不是真正必要的,只会让代码的用户感到困惑。 如果您需要任一数字的默认值,则可以使用

PointList(int max, float max=VALUE)


再次强调:就代码可读性而言,这似乎比代码危害更大。

这需要好好阅读。

整数类型的重载解析发生在两个类别上,可以大致概括为

  • 升级:这是从小于
    int
    的类型转换为
    int
    无符号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);

但这会导致不同的情况。

考虑使用。在客户端代码方面需要付出更多的努力,但可以保证正确性。

我肯定会使用显式构造函数。在本例中,无符号整数不会隐式转换

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)'

这当然是可能的,但我的用户可能不理解其中的区别。其中一些可能不太了解编译器区分浮点和无符号整数的方式。
: error C2668: 'A::A' : ambiguous call to overloaded function
: could be 'A::A(int)'
: or       'A::A(float)'