为什么不使用我的(模板)构造函数进行初始化?

时间:2014-01-18 21:52:03

标签: c++ templates constructor

为什么输出是0003212?

#include <iostream>
using namespace std;

template<typename X> class C
{
public:
    C() { cout<<"0";}
    template<class T> C(const C<T>& c) { cout<<"1";}
    C(const C<int>& c) { cout<<"2";}
    template<class T> C(const C<T*>& c) { cout<<"3";}
};

int main(int argc, char* args[])
{
    C<int> c1;          // 0
    C<double> c2;       // 0
    C<int*> c3;         // 0

    C<int> c4(c3);      // 3
    C<int> c5(c1);      // 2
    C<int> c6(c2);      // 1
    C<float> c7(c1);    // 2
    C<double> c8(c2);   // ?

    std::cin.get();
    return 0;
}

在最后一个含义行中调用了什么?

我可以认为它是一些自动创建的ctor 但无法弄清楚哪一个。

3 个答案:

答案 0 :(得分:5)

这里有几种C ++语言规则。

  1. 模板不能是复制构造函数。 (标准规则12.8p2)

      

    如果第一个参数类型为X,const X&X&,则类volatile X&非模板构造函数是一个复制构造函数}或const volatile X&,并且没有其他参数,或者所有其他参数都有默认参数。

  2. 如果未定义复制构造函数,编译器将生成默认构造函数(如果可能)。 (标准规则12.8p7)

      

    如果类定义没有显式声明复制构造函数,则会隐式声明一个。如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的复制构造函数被定义为已删除;否则,它被定义为默认值(8.4)。如果类具有用户声明的复制赋值运算符或用户声明的析构函数,则不推荐使用后一种情况。因此,对于课程定义

    struct X {
       X(const X&, int);
    };
    
         

    隐式声明了复制构造函数。如果用户声明的构造函数稍后定义为X::X(const X& x, int i =0) { /∗ ... ∗/ }   那么X的复制构造函数的任何使用都是不正确的,因为它含糊不清;无需诊断。

  3. 如果模板和非模板对参数同样匹配,则非模板获胜。 (标准规则13.3.3)规则是一个难以消化的大混乱,我只会展示重要的部分:

      

    [...]一个可行的函数F1被定义为比另一个可行的函数F2更好的函数,如果[...关于参数匹配...的规则],或者,如果不是,F1是非模板函数,F2是函数模板特化[...]

  4. 从您提供的代码中,只有

    C<int>::C(const C<int>&)
    

    是用户定义的复制构造函数,用于打印2X以外的所有int都没有定义复制构造函数,因此编译器会创建一个。{/ p>

    另见

答案 1 :(得分:4)

它是由编译器为您生成的复制构造函数,因为它在最后一种情况下最佳匹配。

答案 2 :(得分:0)

在最后一种情况下,您调用默认的复制构造函数。