This question already has answers here:
Why do multiple-inherited functions with same name but different signatures not get treated as overloaded functions?
(3个答案)
7年前关闭。
考虑以下类别:
在此,给定
那么,为什么要这样呢?如果我们有两个基类,每个基类都有不同的重载,突然之间就会有歧义?
假设我们有:
现在,如果我们说:
编译器提示:
为什么两个运算符重载现在都在Base类中的事实会引起歧义?有解决此问题的方法吗?
编辑:这可能是编译器错误(我正在使用GCC 4.8.1)
也就是说,S(f,base1)与S(f,base2)不同,因此S(f,derived)成为无效的声明集。并且查找失败。
(3个答案)
7年前关闭。
考虑以下类别:
class Foo
{
public:
void operator [] (const std::string& s) { }
void operator [] (std::size_t idx) { }
};
在此,给定
Foo f
的实例,表达式f[0]
并不模棱两可,因为编译器选择了第二个重载。同样,表达式f["abc"]
也不是模棱两可的,因为编译器会选择第一个重载(因为const char*
可转换为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) { }
为什么两个运算符重载现在都在Base类中的事实会引起歧义?有解决此问题的方法吗?
编辑:这可能是编译器错误(我正在使用GCC 4.8.1)
最佳答案
这不是过载解析的问题,而是成员名称查找(在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
中开始查找d.f(0)
时,它将首先调查derived
并发现f
根本无法解析任何内容。然后,10.2/5要求并行进行所有基类的查找,并构造单独的查找集。在这种情况下,S(f,base1)= {base1::f}和S(f,base2)= {base2::f}。然后按照10.2/6中的规则合并这些集合。第一个项目符号是当集合中的一个为空时,或者如果对不同集合的查找以相同成员结尾(考虑到它具有共同的基础)时,则进行合并。第二个项目符号很有趣,因为它适用于此处也就是说,S(f,base1)与S(f,base2)不同,因此S(f,derived)成为无效的声明集。并且查找失败。
关于c++ - []运算符和多重继承的歧义,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19276238/
10-09 21:03