5

给定以下代码:

template<typename T>
class A
{
public:
   T t;
};

class B
{
public:
   void foo(int i) {}

   template<typename T>
   void foo(A<T>& a) {}
};

int main()
{
   A<int> a;
   B      b;

   b.foo(a  );
   b.foo(a.t);
}

这可以编译并正常工作;B::foo()选择并要求a和的正确重载版本a.t

现在我介绍一个新类C,它派生自B并将模板版本::foo()移出B和移入C

template<typename T>
class A
{
public:
   T t;
};

class B
{
public:
   void foo(int i) {}
};

class C: public B
{
public:
   template<typename T>
   void foo(A<T>& a) {}
};

int main()
{
   A<int> a;
   C      c;

   c.foo(a  ); // Fine
   c.foo(a.t); // Error
}

现在代码将不再编译。Visual Studio 2005 声明:

error C2784: 'void C::foo(A<T> &)' : could not deduce template argument for 'A<T> &' from 'int'

事实上,C::foo()使用任何int值调用都会导致此错误。似乎方法重载int被模板重载隐藏了。

为什么会这样?Visual Studio 2005 的编译器有问题吗?不幸的是,我现在无法在任何其他编译器上测试它。

任何信息表示赞赏。

4

3 回答 3

5

似乎 int 的方法重载被模板重载隐藏了。

确切地!您需要向 C 类添加 using 声明:

class C: public B
{
 public:
  using B::foo;
  template<typename T>
  void foo(A<T>& a) {}
};

在派生类中声明成员函数时,基类中的所有同名成员函数都将被隐藏。参见 ISO/IEC 14882:2011 的 §3.3.10/3:

派生类中成员的声明(第 10 条)隐藏了同名基类成员的声明;见 10.2。

于 2012-09-24T16:10:05.877 回答
2

它是隐藏的,没有超载。采用

class C: public B
{
public:
   using B::foo;
   template<typename T>
   void foo(A<T>& a) {}
};
于 2012-09-24T16:10:01.117 回答
1

正确,基本功能是隐藏的。这实际上是它的适当术语。添加using B::foo;到类定义C以取消隐藏它。

于 2012-09-24T16:11:15.570 回答