托管 class 类型作为类型参数 T 的类型(错误 C2670)
Managed class types as type of type parameter T (Error C2670)
我想创建一个返回 ObservableCollection<T>^
类型集合的泛型函数。调用方为类型参数 T
传递托管 class 类型。
这是我对通用函数的尝试之一,之后使用了其他 classes 的解释:
generic<class T>
where T:CAnimal, gcnew()
ObservableCollection<T>^ GetItems(AnimalType animalType, int count)
{
ObservableCollection<T>^ animals = gcnew ObservableCollection<T>();
for (int i = 0; i < count; i++)
{
if (animalType == Dog)
{
CDog^ dog = gcnew CDog(i, count - i);
//CAnimal^ dog = gcnew CDog(i, count - i);
//T dog = gcnew CDog(i, count - i);
//T^ dog = gcnew CDog(i, count - i);
animals->Add(dog);
}
//else if (animalType == Cat) { ... }
//...
}
return animals;
}
因为我尝试了将近 1632 种方法来使该功能起作用,所以我无法告诉您为什么我按原样实现它:-/
Class CAnimal
是 CDog
的基础 class (假设还有更多的动物)。 AnimalType
是一个枚举,旨在用于上述函数以确定实例化和添加到集合的正确 class 类型:
ref class CAnimal
{
public:
CAnimal(){}
CAnimal(int _age) { age = _age; }
int age;
};
ref class CDog : CAnimal {
public:
CDog(){}
CDog(int _age, int _other)
:CAnimal(age), other(_other) {}
int other;
};
enum AnimalType
{
Dog,
Cat,
Fish,
// ...
};
此外,还有一位家长 class 持有 ObservableCollection
的狗、猫等:
ref class CZoo
{
private:
ObservableCollection<CDog^>^ dogs;
public:
CZoo()
{
dogs = GetItems<CDog^>(AnimalType::Dog, 3);
}
};
编译器抛出以下错误:
error C2670: 'System::Collections::ObjectModel::Collection::Add' :
the function template cannot convert parameter 1 from type 'CDog ^'
你能告诉我我做错了什么吗?
!!!解决方案 !!!
基于 ,我最终将构造函数参数移动到一个名为 Initialize
的新函数中,并删除了 enum AnimalTypes
。最终代码改成如下:
ref class CAnimal
{
internal:
virtual void Initialize(int _age, int _other)
{
age = _age;
other = _other;
}
public:
int age;
int other;
};
ref class CDog : CAnimal {};
ref class CCat : CAnimal {};
generic<class T>
where T:CAnimal, gcnew()
ObservableCollection<T>^ GetItems(int count)
{
ObservableCollection<T>^ animals = gcnew ObservableCollection<T>();
for (int i = 0; i < count; i++)
{
T animal = gcnew T();
animal->Initialize(i, count - i);
animals->Add(animal);
}
return animals;
}
ref class CZoo
{
private:
ObservableCollection<CDog^>^ dogs;
ObservableCollection<CCat^>^ cats;
public:
CZoo()
{
dogs = GetItems<CDog^>(3);
cats = GetItems<CCat^>(7);
}
};
如果我删除与错误无关的内容,这就是我们得到的:
generic<class T>
where T:CAnimal, gcnew()
ObservableCollection<T>^ GetItems()
{
ObservableCollection<T>^ animals = gcnew ObservableCollection<T>();
animals->Add(gcnew CDog());
return animals;
}
现在,如果将其作为 GetItems<CCat^>()
调用会怎样?现在您试图将 CDog
放入 CCat
的列表中,但这是行不通的。这就是错误消息所说的:CDog
可能无法转换为 T
。
如果您想这样做,有几个可能的解决方案:
- 您可以 return 列表
CAnimal
代替。 CDog
始终有效,可以放入 CAnimal
. 列表中
- 您可以更改初始化
T
列表的方式。
我推荐后者,然后做这样的事情:
generic<class T>
where T:CAnimal, gcnew()
ObservableCollection<T>^ GetItems(int count)
{
ObservableCollection<T>^ animals = gcnew ObservableCollection<T>();
for (int i = 0; i < count; i++)
{
T animal = gcnew T();
animal->Initialize(i, count-i);
animals->Add(animal);
}
return animals;
}
- 因为你有
gcnew()
约束,这意味着 class 有一个零参数构造函数,你可以只使用类型 T
来调用它.
- 将您当前拥有的构造函数参数移动到
CAnimal
上定义的方法中。这样你就可以在任何 T
. 上调用它
- 我删除了枚举参数。你不需要它;您已经通过通用指定了您想要的动物。
- 无论您如何实施,我都建议您进行此更改。否则,你将不得不考虑像
GetItems<CDog^>(AnimalType::Cat, 3)
这样的事情应该做什么。
我想创建一个返回 ObservableCollection<T>^
类型集合的泛型函数。调用方为类型参数 T
传递托管 class 类型。
这是我对通用函数的尝试之一,之后使用了其他 classes 的解释:
generic<class T>
where T:CAnimal, gcnew()
ObservableCollection<T>^ GetItems(AnimalType animalType, int count)
{
ObservableCollection<T>^ animals = gcnew ObservableCollection<T>();
for (int i = 0; i < count; i++)
{
if (animalType == Dog)
{
CDog^ dog = gcnew CDog(i, count - i);
//CAnimal^ dog = gcnew CDog(i, count - i);
//T dog = gcnew CDog(i, count - i);
//T^ dog = gcnew CDog(i, count - i);
animals->Add(dog);
}
//else if (animalType == Cat) { ... }
//...
}
return animals;
}
因为我尝试了将近 1632 种方法来使该功能起作用,所以我无法告诉您为什么我按原样实现它:-/
Class CAnimal
是 CDog
的基础 class (假设还有更多的动物)。 AnimalType
是一个枚举,旨在用于上述函数以确定实例化和添加到集合的正确 class 类型:
ref class CAnimal
{
public:
CAnimal(){}
CAnimal(int _age) { age = _age; }
int age;
};
ref class CDog : CAnimal {
public:
CDog(){}
CDog(int _age, int _other)
:CAnimal(age), other(_other) {}
int other;
};
enum AnimalType
{
Dog,
Cat,
Fish,
// ...
};
此外,还有一位家长 class 持有 ObservableCollection
的狗、猫等:
ref class CZoo
{
private:
ObservableCollection<CDog^>^ dogs;
public:
CZoo()
{
dogs = GetItems<CDog^>(AnimalType::Dog, 3);
}
};
编译器抛出以下错误:
error C2670: 'System::Collections::ObjectModel::Collection::Add' : the function template cannot convert parameter 1 from type 'CDog ^'
你能告诉我我做错了什么吗?
!!!解决方案 !!!
基于 Initialize
的新函数中,并删除了 enum AnimalTypes
。最终代码改成如下:
ref class CAnimal
{
internal:
virtual void Initialize(int _age, int _other)
{
age = _age;
other = _other;
}
public:
int age;
int other;
};
ref class CDog : CAnimal {};
ref class CCat : CAnimal {};
generic<class T>
where T:CAnimal, gcnew()
ObservableCollection<T>^ GetItems(int count)
{
ObservableCollection<T>^ animals = gcnew ObservableCollection<T>();
for (int i = 0; i < count; i++)
{
T animal = gcnew T();
animal->Initialize(i, count - i);
animals->Add(animal);
}
return animals;
}
ref class CZoo
{
private:
ObservableCollection<CDog^>^ dogs;
ObservableCollection<CCat^>^ cats;
public:
CZoo()
{
dogs = GetItems<CDog^>(3);
cats = GetItems<CCat^>(7);
}
};
如果我删除与错误无关的内容,这就是我们得到的:
generic<class T>
where T:CAnimal, gcnew()
ObservableCollection<T>^ GetItems()
{
ObservableCollection<T>^ animals = gcnew ObservableCollection<T>();
animals->Add(gcnew CDog());
return animals;
}
现在,如果将其作为 GetItems<CCat^>()
调用会怎样?现在您试图将 CDog
放入 CCat
的列表中,但这是行不通的。这就是错误消息所说的:CDog
可能无法转换为 T
。
如果您想这样做,有几个可能的解决方案:
- 您可以 return 列表
CAnimal
代替。CDog
始终有效,可以放入CAnimal
. 列表中
- 您可以更改初始化
T
列表的方式。
我推荐后者,然后做这样的事情:
generic<class T>
where T:CAnimal, gcnew()
ObservableCollection<T>^ GetItems(int count)
{
ObservableCollection<T>^ animals = gcnew ObservableCollection<T>();
for (int i = 0; i < count; i++)
{
T animal = gcnew T();
animal->Initialize(i, count-i);
animals->Add(animal);
}
return animals;
}
- 因为你有
gcnew()
约束,这意味着 class 有一个零参数构造函数,你可以只使用类型T
来调用它. - 将您当前拥有的构造函数参数移动到
CAnimal
上定义的方法中。这样你就可以在任何T
. 上调用它
- 我删除了枚举参数。你不需要它;您已经通过通用指定了您想要的动物。
- 无论您如何实施,我都建议您进行此更改。否则,你将不得不考虑像
GetItems<CDog^>(AnimalType::Cat, 3)
这样的事情应该做什么。
- 无论您如何实施,我都建议您进行此更改。否则,你将不得不考虑像