1

在我的 C++/CLI 代码中,我有大约 20 个不同的类。我已经重载了一个print函数 20 次来处理每个类的一个实例。现在我需要另外支持这 20 个类中的每一个的对象数组,并且讨厌必须编写另外 20 个重载,这些重载大多是彼此的逐字副本。例如,请参见下文:

void print(int i){
  Console::WriteLine("Integer: {0}", i);
}

void print(String ^s){
  Console::WriteLine(L"Hello " + s);
}

generic <typename T>
void print(array<T> ^ts){
  for(int i = 0, n = ts->Length; i < n; ++i)
    print(ts[i]);
}

int main(array<System::String ^> ^args)
{
  array<String^> ^s = gcnew array<String^>{ L"apple", L"ball", L"car" };
  print(s);
  Console::WriteLine(L"Hello World");
  return 0;
}

但上述导致以下错误:

error C2665: 'print' : none of the 2 overloads could convert all the argument types

为什么不编译?我想做的事情的替代方法是什么?

4

2 回答 2

2

无法编译的原因是没有print<T>功能。唯一的print功能是 forintString

C++ 模板可以工作:

template <class T>
void print(array<T> ^ts){
  for(int i = 0, n = ts->Length; i < n; ++i)
    print(ts[i]);
}
于 2013-07-16T19:21:15.900 回答
1

它不编译的原因是,与模板方法不同,泛型方法存在于所有可能的类型中。模板方法仅在调用时创建。由于您仅print使用字符串数组进行调用,因此模板方法定义将编译一个显式采用字符串数组的版本,仅此而已。它将被实现为调用该print(String^)方法,并且不会出现错误。

由于它是通用的,因此该方法只有一个编译版本。如果您将 a 传递T给另一个方法,则该方法必须有一个可以接受任何参数的重载,即使是您未在程序中使用的参数。对于此方法,如果要将 a 传递T给方法,则它必须采用 类型的参数Object^

为了完成这项工作,我将实现print它接受一个对象,并使用反射来查找要打印的类名。

void print(Object^ o)
{
    Console::WriteLine("{0}: {1}", o->GetType()->Name, o);
}

generic <typename T>
void print(array<T> ^ts){
  for(int i = 0, n = ts->Length; i < n; ++i)
    print(ts[i]);
}

如果要为特定类型提供特定版本,请在 print 方法中实现一些附加逻辑:

void print(Object^ o){
  if(o->GetType() == String::typeid)
    Console::WriteLine("Hello {0}", o);
  else
    Console::WriteLine("{0}: {1}", o->GetType()->Name, o);
}

generic <typename T>
void print(array<T> ^ts){
  for(int i = 0, n = ts->Length; i < n; ++i)
    print(ts[i]);
}
于 2013-07-16T19:20:52.937 回答