问题:
在《exceptional c++》一书中描述第5~6问题时,给出一个类fixed_vector的定义,其中包含了两个成员模板函数。《exceptional c++》说明:
这两个函数不能被作为拷贝构造函数和赋值函数,类型O不可能等于类型T;这两个函数也不能阻止编译器自动生成的默认拷贝构造函数和默认赋值函数。
“由于模板构造函数永远都不能成为拷贝构造函数,因此它们的出现并不会妨碍在类中隐式地声明拷贝构造函数。模板构造函数,包括拷贝构造函数,将与其他构造函数一起,共同参与到重载解析中,并且,如果模板构造函数能比其他的构造函数提供更好的匹配,那么可以用它来对对象进行赋值。”
具体代码如下:
2 class fixed_vector
3 {
4 public:
5 typedef T* iterator;
6 typedef const T* const_iterator;
7 fixed_vector() { }
8 template<typename O, size_t osize>
9 fixed_vector( const fixed_vector<O,osize>& other )
10 {
11 copy( other.begin(),
12 other.begin()+min(size,osize),
13 begin() );
14 }
15 template<typename O, size_t osize>
16 fixed_vector<T,size>&
17 operator=( const fixed_vector<O,osize>& other )
18 {
19 copy( other.begin(),
20 other.begin()+min(size,osize),
21 begin() );
22 return *this;
23 }
24 iterator begin() { return v_; }
25 iterator end() { return v_+size; }
26 const_iterator begin() const { return v_; }
27 const_iterator end() const { return v_+size; }
28 private:
29 T v_[size];
30 };
论证:
为了验证书中论述,写两个文件如下:
2
3 #include "iostream"
4 using namespace std;
5
6 template<typename T>
7 class myclass
8 {
9 public:
10 myclass(T para){};
11 private:
12 template<typename O>
13 myclass(myclass<O>& o){ cout << "in_member_template_cotr" << endl; }
14 };
在myclass中,专门将成员模板函数设为private,以测验它是否能够屏蔽默认拷贝构造函数。
2
3 #include "myclass.h"
4
5 int main()
6 {
7 myclass<float> mc_f(47.00);
8 myclass<int> mc_i(47);
9
10 // member_template_cotr_call, failed coz it's private
11 // myclass<int> mc_i1(mc_f);
12
13 // default_copy_cotr_call, failed?
14 myclass<int> mc_i2(mc_i);
15
16 return 0;
17 }
编译结果:
make
g++ -o app main.cc
myclass.h: In function ‘int main()’:
myclass.h:11: error: ‘myclass<T>::myclass(myclass<O>&) [with O = int, T = int]’ is private
main.cc:12: error: within this context
make: *** [all] 错误 1
而将myclass.h中第13行改为
编译链接通过,运行无任何输出(说明调用了默认拷贝构造函数)。
结论:
- 成员模板构造函数不能被当做拷贝构造函数,也不能阻止默认拷贝构造函数和默认赋值函数的生成。模板赋值函数亦然。本例即为拥有成员模板函数,仍然调用了默认拷贝构造函数。
- 默认拷贝构造函数的类型为常引用const&。一开始编译报错,是因为模板函数(接受非const参数)比默认拷贝构造函数(接受const参数)更符合调用的参数传递类型(一个非const参数),因此编译器选择了它【参见结论第三条】,而模板函数本身可见性为private,因此报错。其参数加上const后,则编译器优先选用默认拷贝构造函数,通过。
- 重载函数选择(Overload resolution)动作要先于存取权限检查(access checking)。编译器并不因为模板函数是private而在重载匹配选择时忽略它,可见是先进行重载选择,接下来判断可见性。
原文链接: https://www.cnblogs.com/springlie/archive/2012/11/14/template-copy-constructor.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/69436
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!