C++构造函数模板规则及测试重载报错疑问
规则推导逻辑
首先明确C++标准的两个绑定规则:
- 类的拷贝构造函数有明确定义:只能是非模板构造函数,形如
X(const X&)/X(X&)/X(volatile const X&)等形式的非模板构造才会被识别为拷贝构造。编译器自动生成默认拷贝构造的前提,是用户没有显式声明符合要求的非模板拷贝构造。 - 从函数模板实例化生成的函数,和普通非模板函数是完全独立的两个实体,哪怕签名、名称完全一致,二者也不等价。
两个规则结合就能直接得到书中的结论:构造函数模板属于函数模板,它实例化生成的构造函数哪怕参数类型刚好匹配拷贝构造的要求,本质还是模板生成的函数,不符合拷贝构造“非模板”的定义要求,因此永远不会被编译器识别为用户自定义的拷贝构造,自然也不会替代编译器自动生成的默认拷贝构造。
最常见的场景是写万能引用构造函数template<class U> X(U&&),当传入同类型左值时它会实例化出和拷贝构造签名完全一致的函数,但重载决议时编译器生成的默认非模板拷贝构造优先级更高,不会优先调用这个模板生成的版本。
测试代码报错原因
你的代码报错核心是误将类模板的普通成员函数当成了构造函数模板,实例化后出现了签名完全重复的普通函数。
看你写的两个构造函数:
// 普通非模板构造函数,固定参数类型为const int& entity (int const& y):x(y) { printf("non-template"); } // 注意:这个构造函数没有独立的template<>声明,不是构造函数模板 // 它是类模板entity<T>的普通成员函数,参数类型随类的模板参数T变化 entity (T const& y): x(y) { }
当你实例化entity<int>时,类模板参数T被替换为int,第二个构造函数会被直接实例化为entity(const int&),和第一个构造函数的签名完全一致。同一个类中出现两个签名完全相同的普通成员函数,编译器自然会抛出重定义/无法重载的错误。
如果要验证构造函数模板的特性,需要给构造函数声明独立的模板参数,修正后的可运行测试代码如下:
#include <cstdio> template<class T> class entity { private: int x; public: entity() : x(0) {} entity (int const& y):x(y) { printf("non-template int ctor\n"); } // 构造函数模板有独立的模板参数U,和类模板参数T无关 template<class U> entity (U const& y): x(y) { printf("template generated ctor\n"); } }; int main() { entity<int> en(5); // 匹配度一致时非模板函数优先级更高,打印non-template entity<int> en2(en); // 调用编译器默认生成的拷贝构造,不会走模板实例化版本 }
内容的提问来源于stack exchange,提问作者user17753389
相关产品推荐
相关产品推荐

