c ++ - cli:当调用另一个泛型函数时,为什么调用泛型函数会失败?

时间:2015-10-15 12:27:18

标签: generics c++-cli

以下代码是重现失败的程序和类的基本部分:

using namespace System;

generic <class T>
ref class gener
{
public:
  void func1g (T value)
  {
    Console::WriteLine (value);
    int iValue = static_cast<int>(value);
    if (iValue <= 0) return;
    func2 ();
  }

  void func2 ()
  {
    T value = (T)(Object^)0;
    func1g (value);
  }
};

int main()
{
  gener<int>^ g = gcnew gener<int>;
  int iValue = 1;
  g->func1g (iValue);  // <<=== System.TypeLoadException

  return 0;
}

致电func1g时,我会收到System.TypeLoadException。我只是不明白为什么 是因为func2没有通用参数吗?

这里有完整的错误消息(德语,但它只是说&#39;未处理的例外情况&#39;并且&#39;无法加载&#39 ;;没有详细信息):
enter image description here

C#中的等效代码有效:

public class gener<T>
{
  public void func1g(T value)
  {
    Console.WriteLine(value);
    int iValue = Convert.ToInt32(value);
    if (iValue <= 0) return;
    func2();
  }

  public void func2()
  {
    T value = (T)(object)0;
    func1g(value);
  }
};

internal class Program
{
  private static void Main()
  {
    gener<int> g = new gener<int>();
    int iValue = 1;
    g.func1g(iValue);

    return;
  }
}

修改

我找到了一种解决方法&#39;,请参阅下面的答案,但我不知道为什么会这样做。
如果有人能解释这次失败的原因以及解决方法的功能,我将不胜感激。

编辑2
如果你想重现这个:我使用VS 2008 SP1 我希望它不再像我上一期那样编译器相关,尽管我个人认为这很可能......

2 个答案:

答案 0 :(得分:2)

经过一些测试,我刚刚找到了解决这个特定问题的方法:

我需要按如下方式定义func1g

generic <class T>
void func1g (T value)
{
  ...
}

但我不明白为什么 两种方式(问题中的代码和此解决方案)编译良好,但第一种方式产生运行时异常,请参阅帖子。

还有一个问题:
请注意,上面的func1g是在同一位置声明和定义的! 我的原始代码分为.h和.cpp,如下所示:

generic <class T>
ref class gener
{
public:
  generic <class T>
  void func1g (T value);

  void func2 ()
  {
    T value = (T)(Object^)0;
    func1g (value);
  }
};

generic <class T>
void gener<T>::func1g (T value)
{
  Console::WriteLine (value);
  int iValue = static_cast<int>(value);
  if (iValue <= 0) return;
  func2 ();
}

现在编译器抱怨error C2511: 'void gener<T>::func1g(T)': overloaded member function not found in 'gener<T>'

的cpp

因此我继续玩游戏(它确实是试验和错误)并找到了一个可行的解决方案,我完全不理解:

using namespace System;

generic <class T>
ref class gener
{
public:
  generic <class T2>
  void func1g (T2 value);

  void func2 ()
  {
    T value = (T)(Object^)0;
    func1g (value);
  }
};

generic <class T>
generic <class T2>
void gener<T>::func1g (T2 value)
{
  Console::WriteLine (value);
  int iValue = static_cast<int>(value);
  if (iValue <= 0) return;
  func2 ();
}

int main()
{
  gener<int>^ g = gcnew gener<int>;
  int iValue = 1;
  g->func1g (iValue);

  return 0;
}

有人可以向我解释一下吗? 我实际上并不知道双generic定义是可能的。

答案 1 :(得分:-1)

这是C#代码(顺便说一下,除非TSystem.Int32System.Int32,否则它在C#中也被破坏了,你应该使用default(T)),这在C ++ /中是不合理的CLI。

  void func2 ()
  {
      T value = (T)(object)0;
      func1g(value);
  }

仅仅因为C ++ / CLI编译器接受完全相同的代码,并不意味着它做同样的事情!

object是C#中的关键字,我不知道您为C ++ / CLI添加了哪些宏来进行编译(通常情况下,它不会),但等效的C ++ / CLI类型为{ {1}}(注意句柄)。

无论如何,你只需要一个类型为System::Object^的值初始化项,在C ++中编写为

T