为什么在模板中调用基类的运算符?

时间:2016-07-08 09:03:39

标签: c++ templates inheritance override operator-keyword

为什么B::operator()会在下面的程序中同时调用BD

#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。

1 个答案:

答案 0 :(得分:4)

查看std::sort的签名:

template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp );

参数comp将在此处按值传递,因此对于f(d, vd);d将为slicing copiedB,然后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引用。

LIVE