- 泛化构造函数本质并不是构造函数,而是类型转换函数,并不能替代构造函数,当U与T相等时,会走默认构造函数,如果没有,则编译器会生成一个。
- 注意隐式转换,如果不支持隐形转换,则加explicit
- 泛化构造主要有两个功能,一个是隐式转换,一个是显式调用
- =delete的作用是禁止拷贝构造和禁止拷贝赋值,如果delete掉后,那么显式和隐式都挂掉,具体见图2
- 条款45,shared_ptr就是使用了该特性
- 注意move构造和构造的区别
- class A{A(const B&);}这里就是可以用B构造出A,也是拷贝构造
- testSH< int> t3 =testSH< float>(new int);这里只调用一次构造,并不会走进拷贝构造,因为如果=右边进行构造,其结果是左右两边类型一致,那么我认为会走编译器的默认构造函数,这就是为什么=delete后,会报错!(泛化构造隐式转换也是同理)。但是如果如testSH< int> t3 =testSH< float>(new int);,就必须先构造,再拷贝构造,因为一次构造后类型不一致,需要再转一次!
下图代码,分别为泛化的构造,拷贝构造,拷贝赋值!其中构造不支持隐式转换
具体代码分析
```cpp
template<class T>
class testSH{
public:
int i;
//testSH(const T* _p)=delete;
template<class D>
explict testSH(const D* _p) //不支持隐形转换
{
cout<<"????"<<endl;
}
//template<>
//testSH(T* _p){cout<<"$$$$"<<endl;}
// testSH& operator=(const testSH& tt){
// cout<<"@@@@"<<endl;
// return *this;
// }
template<class D>
testSH& operator=(const testSH<D>& tt)
{
cout<<"####"<<endl;
return *this;
}
//testSH(const testSH& t){cout<<"!!!!"<<endl;};
//testSH(const testSH& t)=delete;
template<class U>
testSH(const testSH<U>& t){cout<<"****"<<endl;};
//testSH& operator=(const testSH&)=delete;
};
//template<class T>
void fun(testSH<int>* a){};
int main()
{
//testSH<int> t = new int; //error1
//fun(new int); //error2
testSH<int> t1(new int);
testSH<int> t3 =testSH<float>(new int);
testSH<int> t4 =new float; //隐形转换,注意这里实际进行了构造,并不会再拷贝构造,但是
//如果testSH(const testSH& t)=delete;则无法进行
testSH<int> t2(new int);
t1 = testSH<float>(new int);
fun(new int);
上图所示,如果testSH的拷贝构造=delete,那么下面泛化拷贝构造也一并失效
template<class T>
class testSH{
public:
int i;
//testSH(const T* _p)=delete;
template<class D>
testSH(const D* _p)
{
cout<<"????"<<endl;
}
//template<>
//testSH(T* _p){cout<<"$$$$"<<endl;}
// testSH& operator=(const testSH& tt){
// cout<<"@@@@"<<endl;
// return *this;
// }
template<class D>
testSH& operator=(const testSH<D>& tt)
{
cout<<"####"<<endl;
return *this;
}
//testSH(const testSH& t){cout<<"!!!!"<<endl;};
//testSH(const testSH& t)=delete;
template<class U>
testSH(const testSH<U>& t){cout<<"****"<<endl;};
//testSH& operator=(const testSH&)=delete;
};
//template<class T>
void fun(testSH<int>* a){};
int main()
{
shared<int> sp1 (new int);
//shared<int> p = sp1;
//testSH<int> t = new int; //error1
//fun(new int); //error2
testSH<int> t1(new int);
testSH<int> t3 =testSH<float>(new int);
这里的t3,需要先构造成float,再拷贝构造,因为必须搞成类型一致才行!
隐式调用
类型转换构造函数,它可以把一个Fuck< U>的类型转换成Fuck,也就是模版参数不同的模版类。这个应用就是比如说我有一个int类型的数组,要用来传递给一个double类型数组的参数,这个构造函数就可以完成这个转换,即可以显示调用,也可以隐式调用。包括:
Fuck (const test& t);
template<typename U> Fuck (const Fuck<U>& t);
Fuck<int> int_f;
Fuck<double> double_f(int_f); // 显示调用
Fuck<double> double_f2 = int_f; // 显示调用2
int my_func(const Fuck<double> & double_f);
my_func(Fuck<double>(int_f)); // 显示调用3
my_func(int_f); // 隐式调用
template<typename T>
T my_func2(T, const Fuck<T>&);
my_func2<double>(0.0, int_f); // 隐式调用2