Почему B::operator()
вызывал как B
, так и D
в программе ниже?Почему оператор из базового класса называется в шаблонах?
#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.
'станд :: sort' принимает компаратор по значению. Настоящий урок здесь состоит в том, что базовые классы, не связанные с листами, должны быть абстрактными, что позволило бы избежать такого рода недоразумений. –