C++/CLI泛型函数实现DBList转CLI List时gcnew T报错如何解决
报错根源
- 泛型参数传入错误:调用函数时传入的泛型参数为
CliMeeting^(跟踪指针类型),此时函数内的T被推导为指针类型,指针类型不存在接收字符串参数的构造函数,gcnew T("BlaBla")语法不成立。 - 泛型约束限制:C++/CLI 仅约束
T继承自CliCommonObjectBase时,编译器无法默认识别T存在接收String^参数的构造函数,且C++/CLI本身不支持指定带参构造函数的泛型约束。
修复方案
方案一(直接可用,无需修改基类)
步骤1:修改泛型调用代码
调用时泛型参数传入实际引用类型,去掉末尾的^符号:
ConvertDataBaseListToList<CliMeeting>(getReadBase()->getTermine());
C++/CLI 中引用类型作为泛型参数时,List<T>内存储的自动就是对应类型的跟踪指针,返回值List<CliMeeting>^等价于你需要的List<CliMeeting^>^效果。
步骤2:调整泛型函数实现,用反射创建实例
通过Activator::CreateInstance反射调用带参构造函数:
using namespace System; generic<typename T> where T : CliCommonObjectBase List<T>^ Converter::ConvertDataBaseListToList(DBList<TMObject> list) { List<T>^ returnList = gcnew List<T>(); for (DBIterator<TMObject> iter = list.first(); !iter.done(); iter.next()) { DBRef<TMObject> tempObject = *iter; // 反射调用接收String^参数的构造函数 T^ instance = (T^)Activator::CreateInstance(T::typeid, gcnew String("BlaBla")); returnList->Add(instance); } return returnList; }
只要你的所有CliCommonObjectBase子类都实现了接收String^参数的构造函数,该实现就可以稳定运行。
方案二(性能更优,需调整基类)
如果不想依赖反射,可以调整基类设计,新增抽象初始化方法:
- 调整
CliCommonObjectBase定义:
public ref class CliCommonObjectBase { protected: // 新增默认构造函数 CliCommonObjectBase() {} // 新增抽象初始化方法,子类必须实现 virtual void Init(String^ objectRefString) = 0; public: // 原有带参构造函数保留 CliCommonObjectBase(String^ objectRefString) { Init(objectRefString); } };
- 调整泛型函数约束与实现:
generic<typename T> where T : CliCommonObjectBase, gcnew() List<T>^ Converter::ConvertDataBaseListToList(DBList<TMObject> list) { List<T>^ returnList = gcnew List<T>(); for (DBIterator<TMObject> iter = list.first(); !iter.done(); iter.next()) { DBRef<TMObject> tempObject = *iter; T^ instance = gcnew T(); instance->Init("BlaBla"); returnList->Add(instance); } return returnList; }
该方案不需要反射,运行性能更高,编译期就能检查类型合法性。
内容的提问来源于stack exchange,提问作者user7843400
相关产品推荐
相关产品推荐

