代码之家  ›  专栏  ›  技术社区  ›  James Thompson

C++中隐式类型转换的管理

  •  2
  • James Thompson  · 技术社区  · 15 年前

    我正在研究做最近邻居查询的代码。用户在搜索中如何查询数据有两个简单的基础思想:

    • 与空间中给定点最近的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++,有时没有正规教育的好处。谢谢!

    7 回复  |  直到 15 年前
        1
  •  5
  •   Johannes Schaub - litb    15 年前

    整数类型的重载解析发生在两个类别上,可以非常粗略地概括为

    • 促销:这是从小于 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 例如。对于另一个双参数构造函数,如果需要,可以使用解决方案。


    也就是说,我也会使用工厂函数,因为我认为决定参数类型的意义是非常脆弱的。大多数人都希望下面的结果相等

    PointList p(floor(1.5));
    PointList u((int)1.5);
    

    但这会导致另一种情况。

        2
  •  6
  •   Hans Malherbe    15 年前

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

    
    static PointList createNearestValues(unsigned int maxvals) {}
    static PointList createByDistance(float maxdist) {}
    
        3
  •  2
  •   DannyT    15 年前

    考虑使用 true typedefs . 在您的客户机代码方面,这是一项更大的工作,但是您可以保证正确性。

        4
  •  1
  •   Burkhard    15 年前

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

    第二种情况下,您也可以使用10.0。

        5
  •  1
  •   pmr    15 年前

    如果存在构造函数1和2,则在插入的值为float或int且不应进行转换的情况下,将调用正确的构造函数。因此,只需确保将用于显式调用的数字类型(即1f和1)设置为显式。 构造函数3似乎不是一个很好的选择,因为它不是真正必要的,只会混淆代码的用户。 如果需要任何一个数字的默认值,可以使用

    PointList(int max, float max=VALUE)
    

    PointList(float max, int max=VALUE)
    

    再次说明:在代码可读性方面,这似乎比代码更有害。

        6
  •  1
  •   Ariel    15 年前

    这需要一个好的阅读 Overload Resolution .

        7
  •  0
  •   mandrake    15 年前

    我肯定会用 明确的 构造函数。在示例中,无符号整数不隐式转换。

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