当我使用这样的代码时,我似乎得到了意外的结果:
class Base
{
public:
template <typename T>
bool operator <<(int(*fx)(T)) {
return true;
}
};
class Sub : public Base
{
public:
template <typename T>
bool operator <<(T t) {
return false;
}
};
int foo(int a) {
return a;
}
int main() {
bool test = Sub() << foo;
std::cout << "Used " << (test ? "Base" : "Sub") << " class function";
}
该代码将使用非常通用的Sub类函数,而不是GCC 4.6.3和VS C ++ v141上的专用Base类函数。
但是我希望它能做的更像是这段代码:
class AClass
{
public:
template <typename T>
bool operator <<(int(*fx)(T)) {
return true;
}
template <typename T>
bool operator <<(T t) {
return false;
}
};
int foo(int a) {
return a;
}
int main() {
bool test = AClass() << foo;
std::cout << "Used " << (test ? "Specialized" : "Generic") << " class function";
}
另一方面,此代码将使用GCC 4.6.3和VS C ++ v141上预期的专用功能。
这是我的问题:
您看到的行为对于该示例是正确的。
当C ++遇到二进制运算符expression时A << B
,它将查找三种函数和函数模板声明:
通过成员名称查找表达式可以找到的功能 A.operator<<
通过表达式的依赖于参数的查找将找到的函数 operator<<(A, B)
一组伪声明来表示运算符的内置含义,例如 int operator<<(int, int);
通过这种方法找到的全部功能组合将在整个过载解决过程中运行,以找到最佳的过载。
您的示例中的问题在于,在第一个项目符号中,对的成员名称查找的结果Sub().operator<<
仅包含中的功能模板Sub
,而不包含中的其他功能模板Base
。这是派生类的正常“隐藏”规则:除非另有说明,否则派生类的任何成员都将隐藏所有具有相同名称的继承成员-即使该名称是像“ operator<<
”这样的奇特名称。
解决隐藏问题的简单方法是在“取消隐藏”继承的成员中添加一个using
声明:
class Sub : public Base
{
public:
template <typename T>
bool operator <<(T t) {
return false;
}
using Base::operator<<; // NOTE
};
该修改的示例程序然后打印“使用的基础类的函数”,因为现在两个成员都可以用于重载可见,并且Base::operator<<
模板功能更专业比Sub::operator<<
模板函数。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句