【问题标题】:Why using declaration is needed when an overload is deleted为什么删除重载时需要使用声明
【发布时间】:2023-03-25 21:07:01
【问题描述】:
为什么我必须重新引入删除了一些重载的函数的名称?
#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"));
}
【问题讨论】:
标签:
c++
class
scope
function-declaration
using-declaration
【解决方案1】:
结构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
【解决方案2】:
这是合法的,但至少是一致的。
我想你在想,当一个函数在派生类中被重写时,基类中的函数,或者至少是它的标识符,在概念上被导入派生类,然后 被覆盖。但实际上,正在发生的事情是调用b.f 的代码甚至从未看到 A::f,因为查找在到达那里之前就成功了。所有这些都发生在重载决议发生之前。
因此,如果您想访问来自A 的各种重载以及B 的各种重载(包括已删除的重载),则需要将它们导入B,因此编译器之前不会放弃看到他们。
【解决方案3】:
B 类中的单个 f 声明隐藏了基类 A 中 f 的所有声明。
甚至将函数标记为已删除也被视为声明。