c++ - 模板更喜欢子类函数而不是更专业的继承函数

标签 c++

当我使用这样的代码时,我似乎得到了意想不到的结果:

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";
}

此代码将使用非常通用的子类函数,而不是 GCC 4.6.3 和 VS C++ v141 上的专用基类函数。

但我希望它做的更像这段代码:

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++遇到二元运算符表达式A << B时, 它寻找三种函数和函数模板声明:

  • 通过成员名称查找表达式 A.operator<< 可以找到的函数

  • 将通过参数相关查找表达式 operator<<(A, B) 找到的函数

  • 一组虚拟声明来表示运算符的内置含义,例如 int operator<<(int, int);

通过重载解析过程运行以这种方式找到的全部组合函数集,以找到最佳重载。

您的示例中的问题是,在第一个项目符号中,成员名称查找结果 Sub().operator<<只包含Sub中的函数模板,而不是 Base 中的其他函数模板.这是派生类的正常“隐藏”规则:除非另有说明,否则派生类的任何成员都隐藏所有具有相同名称的继承成员 - 即使该名称是一个奇特的名称,如“operator<<”。

绕过隐藏的简单方法是添加 using declaration “取消隐藏”继承的成员:

class Sub : public Base
{
public:
    template <typename T>
    bool operator <<(T t) {
        return false;
    }
    using Base::operator<<; // NOTE
};

modified example program然后打印“Used Base class function”,因为现在两个成员对于重载解析都是可见的,并且 Base::operator<<模板函数比 Sub::operator<< 更专业模板函数。

关于c++ - 模板更喜欢子类函数而不是更专业的继承函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54045927/

相关文章:

c++ - 无限循环 vs boost::asio::deadline_timer C++ 性能

c++ - 如何在 std::function 中捕获 unique_ptr

c++ - 为 C++ 选择 begin() 和 end()

c++ - calibrateCamera opencv 功能不起作用

c++ - 为什么 C++17 类模板参数推导失败?

c++ - C++ 字符串附加和运算符 += 之间的区别

c++ - C 或 C++ Win32 如何获取程序中运行的线程数?

C++ - 二维数组作为方法参数

c++ - 用 Shift left 或 Shift right 计算对数底数 n

c++ - 命令行参数 c++