模板类初始化赋值报conversion to non-scalar type错误的解决方法
模板类跨类型初始化赋值错误的解决方案
问题描述
执行TemplateTest<int> t3 = t2;(其中t2为TemplateTest<double>类型)进行初始化时触发conversion to non-scalar type错误,但先声明TemplateTest<int> t3;再执行t3 = t2;的赋值操作却能正常运行。
完整代码
#include <iostream> using namespace std; template <typename T> class TemplateTest { private: T m_data; public: TemplateTest(); TemplateTest(const T inputData); T GetData() const; template<class U> TemplateTest<T>& operator= (const TemplateTest<U> &rhs); void Print(); }; template <class T> TemplateTest<T>::TemplateTest() { m_data = 0; } template <class T> TemplateTest<T>::TemplateTest(const T inputData) { m_data = inputData; } template <class T> void TemplateTest<T>::Print() { std::cout<<m_data<<std::endl; } template <class T> T TemplateTest<T>::GetData() const { return m_data; } template<class T> template<class U> TemplateTest<T>& TemplateTest<T>::operator= (const TemplateTest<U> &rhs) { m_data = rhs.GetData(); return *this; } int main() { TemplateTest<int> t1(12); TemplateTest<double> t2(1.2); TemplateTest<int>t3 = t2; t3.Print(); return 0; }
原因分析
TemplateTest<int> t3 = t2;属于拷贝初始化,编译器需要将TemplateTest<double>转换为TemplateTest<int>,这依赖于类中存在可以接受TemplateTest<U>类型参数的转换构造函数。t3 = t2;属于赋值操作,调用的是你已经显式定义的模板版operator=,因此可以正常执行。
你的类仅提供了接受T类型的构造函数,没有定义支持跨模板实例转换的构造函数,导致拷贝初始化失败。
解决方案
给模板类添加一个模板版的转换构造函数:
1. 更新类声明
在TemplateTest类的public区域添加构造函数声明:
template<class U> TemplateTest(const TemplateTest<U>& rhs);
修改后的类声明:
template <typename T> class TemplateTest { private: T m_data; public: TemplateTest(); TemplateTest(const T inputData); // 新增跨类型转换构造函数 template<class U> TemplateTest(const TemplateTest<U>& rhs); T GetData() const; template<class U> TemplateTest<T>& operator= (const TemplateTest<U> &rhs); void Print(); };
2. 实现转换构造函数
在类外添加模板构造函数的实现:
template<class T> template<class U> TemplateTest<T>::TemplateTest(const TemplateTest<U>& rhs) { m_data = rhs.GetData(); }
修改后的完整代码
#include <iostream> using namespace std; template <typename T> class TemplateTest { private: T m_data; public: TemplateTest(); TemplateTest(const T inputData); template<class U> TemplateTest(const TemplateTest<U>& rhs); T GetData() const; template<class U> TemplateTest<T>& operator= (const TemplateTest<U> &rhs); void Print(); }; template <class T> TemplateTest<T>::TemplateTest() { m_data = 0; } template <class T> TemplateTest<T>::TemplateTest(const T inputData) { m_data = inputData; } template<class T> template<class U> TemplateTest<T>::TemplateTest(const TemplateTest<U>& rhs) { m_data = rhs.GetData(); } template <class T> void TemplateTest<T>::Print() { std::cout<<m_data<<std::endl; } template <class T> T TemplateTest<T>::GetData() const { return m_data; } template<class T> template<class U> TemplateTest<T>& TemplateTest<T>::operator= (const TemplateTest<U> &rhs) { m_data = rhs.GetData(); return *this; } int main() { TemplateTest<int> t1(12); TemplateTest<double> t2(1.2); TemplateTest<int> t3 = t2; t3.Print(); return 0; }
补充说明
- 拷贝初始化过程中,编译器优先匹配拷贝/转换构造函数,而非赋值运算符
- 模板类不会自动生成跨实例类型的转换构造函数,必须显式定义才能支持此类操作
内容的提问来源于stack exchange,提问作者Renu
相关产品推荐
相关产品推荐

