为什么在模板中调用基类中的运算符
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
将切片复制到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 引用。
住
相关文章:
- 如何使基类的运算符对基类的可变参数数可见(请参阅下面的代码)?
- 基类和派生类的多态赋值运算符
- 模板基类中的重载运算符
- 为什么基类中的复制和交换会导致派生类中的复制赋值运算符被隐式删除?
- 如何从派生类访问基类中的重载运算符?
- 调用以CWinThread为基的类运算符()的std::thread失败
- 基类和派生类的虚拟插入运算符重载
- 派生类 插入和提取运算符重载以及基类与派生类之间的强制转换
- 如何在C++上的多个继承上下文上使用特定基类中的运算符
- 如何通过带有指向基类的指针的删除运算符释放内存
- 无法在赋值运算符中访问基类的受保护方法
- 如何在抽象基类中实现运算符+
- 将多态性与运算符 + 重载模板化类结合使用.如何实现基类?
- 从参数包中派生的调用基类运算符 =
- 为什么不能从派生类调用基类运算符?
- 要求基类运算符执行"domain check" (C++)
- 为什么派生类不使用基类运算符=(赋值运算符)?
- C++-对基类运算符的未定义引用
- 为什么派生类调用基类运算符而不是它自己的运算符
- 重载基类>>运算符