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

频道72

考虑以下类别:

class Foo
{
    public:

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

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

在此,给定的实例Foo f,该表达式f[0]不是模棱两可的,因为编译器选择了第二个重载。同样,表达式f["abc"]也不是模棱两可的,因为编译器会选择第一个重载(因为aconst char*可以转换为an std::string)。

那么,为什么要这样呢?如果我们有两个基类,每个基类都有不同的重载,突然之间就会有歧义?

假设我们有:

class Base1
{
    public:

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

class Base2
{
    public:

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

class Derived : public Base1, public Base2
{ };

现在,如果我们说:

Derived d;
d[0];

编译器抱怨:

    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) { }

为什么两个运算符重载现在都在基类中的事实导致任何歧义?有解决此问题的方法吗?

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

大卫·罗德里格斯(DavidRodríguez)-德里贝斯

这不是过载解析的问题,而是成员名查找(在10.2中定义)。考虑(因为我不想operator[]在任何地方):

struct base1 { void f(int); };
struct base2 { void f(double); };
struct derived : base1, base2 {};
int main() {
   derived d; d.f(0);
}

f在postfix表达式中开始查找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,derived)成为无效的声明集。并且查找失败。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

通过继承的运算符重载会导致歧义

来自分类Dev

MSVC:具有模板化转换运算符和多重继承的错误

来自分类Dev

关于多重继承和歧义

来自分类Dev

模板继承和运算符

来自分类Dev

运算符<<和继承/组成

来自分类Dev

模板继承和运算符

来自分类Dev

运算符<<和继承/组成

来自分类Dev

Swift运算符和继承

来自分类Dev

运算符“ +”的歧义使用

来自分类Dev

运算符'!='的歧义使用?

来自分类Dev

与转换运算符和构造函数的歧义

来自分类Dev

运算符继承

来自分类Dev

C ++:运算符重载:类内和类外。与预递增运算符的歧义

来自分类Dev

了解多重成本。和->运算符使用?

来自分类Dev

运算符[](const char *)的歧义

来自分类Dev

一元运算符的歧义

来自分类Dev

reverse_iterator的歧义!=运算符

来自分类Dev

使用<< >>运算符时的歧义

来自分类Dev

Swift“歧义使用运算符'=='”

来自分类Dev

一元运算符的歧义

来自分类Dev

继承-运算符重载

来自分类Dev

ECMAScript / JavaScript-继承和新运算符

来自分类Dev

函数调用运算符的继承和重载

来自分类Dev

C ++类模板继承和运算符=

来自分类Dev

继承中的此运算符和私有变量

来自分类Dev

接口的多重继承歧义

来自分类Dev

g ++和clang ++-删除由重载转换运算符歧义获取的指针

来自分类Dev

指向重载const成员函数和成员运算符的歧义指针

来自分类Dev

PHP多重逻辑运算符