请考虑以下代码:
#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;
}
Run Code Online (Sandbox Code Playgroud)
产生以下输出:
T&
T&
T*
const T&
const T*
Run Code Online (Sandbox Code Playgroud)
这个输出让我感到惊讶,因为我认为最接近匹配的函数是被调用的函数.所以我期待输出:
A&
A&
A*
const A&
const A*
Run Code Online (Sandbox Code Playgroud)
有人解释为什么当我传入基类(A)的子类(B)时,基类重载选择了模板函数重载?
这是预期的行为.你打电话的时候foo(a); a是B.所以我们需要从a B到a 的隐式转换A才能调用void foo(A& a).但是既然你也有
template <class T>
void foo(T& a) {
cout << "T&" << endl;
}
Run Code Online (Sandbox Code Playgroud)
模板被剔除,你得到了void foo(B& a).这是直接匹配,无需转换.这是最好的功能,这就是它被选中的原因.对于所有其他函数来说,这是相同的,并且T推导出B与所有A函数相比更好的匹配.
如果你想停止这个,你可以使用std::enable_if并检查类型是否是派生类std::is_base_of
| 归档时间: |
|
| 查看次数: |
59 次 |
| 最近记录: |