模板类中的类型转换运算符 - 无论显式是否调用

时间:2011-12-11 13:45:28

标签: c++ templates type-conversion

我有这个代码。在主要我想要使用类型转换,但使用调试我明白在这一行 ob2=(Point2D<double>)ob1;

无论template <class T1> Point2D(Point2D<T1>& ob)之前是什么,都会调用

构造函数explicit,例如template <class T1> explicit Point2D(Point2D<T1>& ob)为什么会发生这种情况?我希望调用operator Point2D<T1>()

template <class T>
class Point2D
{
public:
    T x;
    T y;
    Point2D(T _x=0,T _y=0):x(_x),y(_y)
    {
    }
    Point2D(Point2D& ob)
    {
        x=ob.x;
        y=ob.y;
    }
    template <class T1>
    Point2D(Point2D<T1>& ob)
    {
        x=ob.x;
        y=ob.y;
    }
    template <class T1>
    operator Point2D<T1>()
    {
        return Point2D<T1>(x,y);
    }
};
int main()
{
    Point2D<int> ob1(10,10);
    Point2D<double> ob2(20,20);
    ob2=(Point2D<double>)ob1;
    return 0;
}

2 个答案:

答案 0 :(得分:3)

标准的[dcl.init]部分指定在初始化期间首选构造函数:

  

如果目标类型是(可能是cv限定的)类类型:

     
      
  • 如果初始化是直接初始化,或者它是复制初始化,其中源类型的cv-nonqualified版本与目标类的类相同,或者是派生类,构造函数被视为。列举了适用的构造函数(13.3.1.3),并通过重载解析(13.3)选择最佳构造函数。调用所选的构造函数来初始化对象,初始化表达式或表达式列表作为其参数。如果没有构造函数适用,或者重载决策不明确,则初始化是不正确的。
  •   
  • 否则(即,对于剩余的复制初始化情况),用户定义的转换序列可以从源类型转换为目标类型或(当使用转换函数时)转换为其派生类如13.3.1.4所述进行列举,最好的一类通过重载决议(13.3)选择。如果转换不能完成或不明确,则初始化是错误的。选择的函数以初始化表达式作为参数调用;如果函数是构造函数,则调用初始化目标类型的cv-nonqualified版本的临时函数。临时是一个prvalue。然后,根据上述规则,调用的结果(对于构造函数的情况是临时的)用于直接初始化作为复制初始化目标的对象。在某些情况下,允许实现通过将中间结果直接构造到正在初始化的对象中来消除此直接初始化中固有的复制;见12.2,12.8。
  •   

此规则意味着只有在没有构造函数适用的情况下才会考虑用户定义的转换序列。

强制转换使用与初始化相同的规则,请参阅[expr.static.cast]

  

如果声明e格式正确,则可以使用T形式的static_cast将表达式static_cast<T>(e)显式转换为T t(e);类型,对于一些发明的临时变量t(8.5)。

[expr.cast]

  

执行的转化      
      
  • a const_cast(5.2.11),
  •   
  • a static_cast(5.2.9),
  •   
  • a static_cast后跟const_cast
  •   
  • a reinterpret_cast(5.2.10)或
  •   
  • a reinterpret_cast后跟const_cast
  •   
     

可以使用显式类型转换的强制转换表示法执行。

另请注意[class.conv.ctor]

  

显式构造函数与非显式构造函数一样构造对象,但仅在显式使用直接初始化语法(8.5)或强制转换(5.2.9,5.4)的情况下才这样做。

答案 1 :(得分:1)

在用户定义的转换函数的情况下,模板参数推断是不可能的:

template <class T1>
operator Point2D<T1>()
{
    return Point2D<T1>(x,y);
}

编译器如何推导出模板参数T1?它没有参与参数列表。仅当模板参数参与函数参数列表时,才可能进行模板参数推导。

由于无法进行模板参数推导,因此会调用构造函数。

希望有所帮助。