Visual Studio 基类运算符在子类中删除[重复]

gg0vcinb  于 2023-05-18  发布在  其他
关注(0)|答案(1)|浏览(188)

此问题已在此处有答案

Why does an overridden function in the derived class hide other overloads of the base class?(4个答案)
2天前关闭。
下面是一个简单的例子,它再现了我遇到的问题:

class Base
{
public:
    Base() {}
    Base(int value) {}
    Base& operator[](int index) { return Base(); }
    Base& operator[](const char* index) { return Base(); }
};

class IntChild : public Base
{
    Base& operator[](const char* index) = delete;
};

IntChild test;
test[4] = 1; //Error: no operator "[]" matches these operands

在基类中实现了两个运算符[]。在子类中删除以const char*为参数的运算符。但是,当子类中的operator[](const char*)被删除时,使用运算符取integer时也会发生错误:
没有运算符“[]”匹配这些操作数
我正在使用Visual Studio 2019。
我错过了什么?

2skhul33

2skhul331#

使用Base::operator[];在派生类中将其引入作用域:

struct Base
{
    Base() = default;
    Base(int value) {}
    Base& operator[](int index) { return *this; }
    Base& operator[](const char* index) { return *this; }
};

struct IntChild : public Base
{
    using Base::operator[];
    Base& operator[](const char* index) = delete;
};

IntChild test;
test[4] = 1; //works

下面是using-declaration的相关摘录,它解释了为什么在添加using之后,你可以在基类中调用int-重载:

在类定义中

Using-declaration将基类的成员引入到派生类定义中,例如将基类的受保护成员公开为派生的公共成员。在这种情况下,nested-name-specifier必须命名正在定义的基类。如果名称是基类的重载成员函数的名称,则引入具有该名称的所有基类成员函数。如果派生类已经有一个具有相同名称、参数列表和限定的成员,则派生类成员将隐藏或重写(不与之冲突)从基类引入的成员。
为什么没有using,它不会退回到基类operator[](int)的问题可以用unqualified name lookup来回答(特别是下面的b点):

类定义

对于在类定义(包括基类说明符和嵌套类定义)中任何地方使用的名称,除了在成员函数体内部、成员函数的默认参数、成员函数的异常说明或默认成员初始化器内部,其中成员可能属于定义在封闭类的主体中的嵌套类,搜索以下范围:
a)在使用点之前使用名称的类的主体
B)其基类的整个主体,当找不到声明时递归到它们的基类
因此,一旦在派生类中找到一个声明,就不必继续在基类中搜索函数。请注意,当你实现派生类时,这也成立(不仅仅是当你=delete它时)。

相关问题