为什么在模板中调用来自 base class 的运算符?
Why is operator from base class called in templates?
为什么在下面的程序中 B
和 D
都调用了 B::operator()
?
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
class B {
public:
virtual ~B() {}
virtual bool operator()(int a, int b) { return a < b; }
};
class D : public B {
public:
bool operator()(int a, int b) override { return a > b; }
};
void f(B& b, std::vector<int>& v)
{
std::sort(v.begin(), v.end(), b);
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
}
int main()
{
const std::vector<int> v{5, 3, 8, 1, 7};
std::vector<int> vb(v);
B b;
f(b, vb);
std::vector<int> vd(v);
D d;
f(d, vd);
return 0;
}
如果我将 std::sort(v.begin(), v.end(), b)
更改为:
std::sort(v.begin(), v.end(),
[&](int x, int y){ return b.operator()(x, y); });
然后 f(d, vd)
按预期向后排序。
我最好的理解是 std::sort(v.begin(), v.end(), b)
使用 &B::operator()
而不是 b.operator()
。虽然我找不到明确的解释,而且它似乎并不完全合乎逻辑,因为编译器应该能够看到 B
有一个 vtable。
见std::sort
的签名:
template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp );
参数comp
这里会传值,所以对于f(d, vd);
,d
会是slicing copied到B
然后B::operator()
将被调用。
您可以将 f()
设为模板函数。
template <typename COMP>
void f(COMP& b, std::vector<int>& v)
{
std::sort(v.begin(), v.end(), b);
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
}
其他建议:最好使B::operator()
和D::operator()
成员函数为const,并将b
的参数类型改为const reference。
为什么在下面的程序中 B
和 D
都调用了 B::operator()
?
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
class B {
public:
virtual ~B() {}
virtual bool operator()(int a, int b) { return a < b; }
};
class D : public B {
public:
bool operator()(int a, int b) override { return a > b; }
};
void f(B& b, std::vector<int>& v)
{
std::sort(v.begin(), v.end(), b);
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
}
int main()
{
const std::vector<int> v{5, 3, 8, 1, 7};
std::vector<int> vb(v);
B b;
f(b, vb);
std::vector<int> vd(v);
D d;
f(d, vd);
return 0;
}
如果我将 std::sort(v.begin(), v.end(), b)
更改为:
std::sort(v.begin(), v.end(),
[&](int x, int y){ return b.operator()(x, y); });
然后 f(d, vd)
按预期向后排序。
我最好的理解是 std::sort(v.begin(), v.end(), b)
使用 &B::operator()
而不是 b.operator()
。虽然我找不到明确的解释,而且它似乎并不完全合乎逻辑,因为编译器应该能够看到 B
有一个 vtable。
见std::sort
的签名:
template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp );
参数comp
这里会传值,所以对于f(d, vd);
,d
会是slicing copied到B
然后B::operator()
将被调用。
您可以将 f()
设为模板函数。
template <typename COMP>
void f(COMP& b, std::vector<int>& v)
{
std::sort(v.begin(), v.end(), b);
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
}
其他建议:最好使B::operator()
和D::operator()
成员函数为const,并将b
的参数类型改为const reference。