考虑以下代码:
#include <cstdlib>
#include <iostream>
using std::cout;
using std::endl;
class A {
public:
virtual ~A() {
}
};
class B : public A {
};
void foo(A& a) {
cout << "A&" << endl;
}
void foo(const A& a) {
cout << "const A&" << endl;
}
void foo(A* a) {
cout << "A*" << endl;
}
void foo(const A* a) {
cout << "const A*" << endl;
}
template <class T>
void foo(T& a) {
cout << "T&" << endl;
}
template <class T>
void foo(const T& a) {
cout << "const T&" << endl;
}
template <class T>
void foo(T* a) {
cout << "T*" << endl;
}
template <class T>
void foo(const T* a) {
cout << "const T*" << endl;
}
int main(int argc, char** argv) {
B a;
foo(a);
B& b = a;
foo(b);
B* c = &a;
foo(c);
const B& d = a;
foo(d);
const B* e = &a;
foo(e);
return EXIT_SUCCESS;
}
产生以下输出:
T&
T&
T*
const T&
const T*
这个输出让我感到惊讶,因为我认为最接近匹配的函数将被调用。所以我期待输出:
A&
A&
A*
const A&
const A*
有人可以解释为什么当我传入基类 (A) 的子类 (B) 时选择模板函数重载而不是基类重载吗?
最佳答案
这是预期的行为。当你调用 foo(a);
时,a
是一个 B
。所以我们需要从 B
到 A
的隐式转换,以便调用 void foo(A& a)
。但是因为你也有
template <class T>
void foo(T& a) {
cout << "T&" << endl;
}
模板被删除,你得到 void foo(B& a)
。这是直接匹配,不需要转换。这是最好的功能,所以这就是它被选中的原因。这对于所有其他函数都是相同的,T
被推导为 B
,这比所有 A
函数提供更好的匹配.
如果你想停止这个,你可以使用 std::enable_if
并检查类型是否为派生类 std::is_base_of
关于c++ - 使用子类调用时重载函数模板匹配模板而不是基类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39044153/