为什么删除重载时需要使用声明

Why using declaration is needed when an overload is deleted

为什么我必须重新引入删除了一些重载的函数的名称?

#include <string>

struct A
{
    void f(int) {}
    void f(double) {}
    void f(const std::string&) {}
};

struct B : public A
{
    using A::f; // needed to compile : why ?
    void f(int)=delete;
    void f(double)=delete;
};

int main()
{
    B b;
    b.f(std::string("toto"));
}

B class 中 f 的单个声明隐藏了 所有 f 的声明 A class.

甚至将函数标记为已删除也被视为声明。

结构B内的这些记录

void f(int)=delete;
void f(double)=delete;

是在基础结构A中隐藏同名f声明的声明。

所以B中的using声明

using A::f; // needed to compile : why ?

使在 A 中声明的名称为 f 的所有函数在结构 B 中可见。

考虑以下演示程序,在一种情况下没有 using 声明,在第二种情况下有 using 声明。

#include <iostream>

int main() 
{
{   
    struct A
    {
        void f( char ) const
        {
        std::cout << "A::f( char ) const\n";
        }
    };

    struct B : A
    {
        void f( int ) const
        {
            std::cout << "B::f( int ) const\n";
        }
    };


    B b;
    
    b.f( 'A' );
}

std::cout << '\n';

{   
    struct A
    {
        void f( char ) const
        {
        std::cout << "A::f( char ) const\n";
        }
    };

    struct B : A
    {
        using A::f;
        void f( int ) const
        {
            std::cout << "B::f( int ) const\n";
        }
    };


    B b;
    
    b.f( 'A' );
}

    return 0;
}

程序输出为

B::f( int ) const

A::f( char ) const

虽然墨守成规,但至少是一贯的。

我想你在想,当一个函数在派生 class 中被覆盖时,其机制是来自基础 class 的函数,或者至少它的标识符,在概念上是输入派生 class 和 then 覆盖。但实际上,正在发生的是调用 b.f 的代码甚至从未 看到 A::f,因为查找在到达那里之前就成功了。在重载决议发生之前发生的所有事情。

因此,如果您想访问 A 中的各种重载以及 B 中的各种重载(包括已删除的重载),则需要将它们导入 B,因此编译器在看到它们之前不会放弃。