使用[]运算符和多重继承的歧义

Cha*_*l72 11 c++

考虑以下课程:

class Foo
{
    public:

    void operator [] (const std::string& s) { }

    void operator [] (std::size_t idx) { }
};
Run Code Online (Sandbox Code Playgroud)

这里,给定一个实例Foo f,表达式f[0]不含糊,因为编译器选择第二个重载.同样,表达式f["abc"]不含糊,因为编译器选择第一个重载(因为a const char*可以转换为a std::string).

那么,为什么呢,如果我们有两个Base类,每个都有不同的重载,那么突然有歧义?

假设我们有:

class Base1
{
    public:

    void operator [] (const std::string& s) { }
};

class Base2
{
    public:

    void operator [] (std::size_t idx) { }
};

class Derived : public Base1, public Base2
{ };
Run Code Online (Sandbox Code Playgroud)

现在,如果我们说:

Derived d;
d[0];
Run Code Online (Sandbox Code Playgroud)

编译器抱怨:

    error: request for member ‘operator[]’ is ambiguous
      d[0];
         ^
   note: candidates are: void Base2::operator[](std::size_t)
      void operator [] (std::size_t idx) { }
           ^
   note:                 void Base1::operator[](const string&)
      void operator [] (const std::string& s) { }
Run Code Online (Sandbox Code Playgroud)

为什么两个运算符重载现在都在Base类中会导致任何歧义?有没有办法解决这个问题?

编辑:这可能是编译器错误(我正在使用GCC 4.8.1)

Dav*_*eas 9

这不是重载解析的问题,而是成员名称查找,它在10.2中定义.考虑(因为我不想operator[]到处写):

struct base1 { void f(int); };
struct base2 { void f(double); };
struct derived : base1, base2 {};
int main() {
   derived d; d.f(0);
}
Run Code Online (Sandbox Code Playgroud)

f在后缀表达式中查找开始时d.f(0),它将首先查看derived并找到f根本不解析的任何内容.10.2/5然后要求查找并行进行到所有基类,构建单独的查找集.在这种情况下,S(f,base1)= {base1 :: f}S(f,base2)= {base2 :: f}.然后按照10.2/6中的规则合并这些集合.当其中一个集合为空或者不同集合的查找以相同成员结束时(考虑到它达到共同基础),第一个子弹处理合并.第二个子弹是有趣的,因为它适用于此

10.2/6子弹2

否则,如果声明组S的(F,BI)和S(F,C)不同,合并是模棱两可:新S(F,C)与一个无效的声明集和子对象的工会设置查找集.在后续合并中,无效的声明集被认为与其他任何不同.

也就是说,S(f,base1)S(f,base2)不同,因此S(f,导出)成为无效的声明集.查找失败.


归档时间:

查看次数:

519 次

最近记录:

12 年,1 月 前