C++:即使在每个继承级别具有唯一的函数名称,函数调用也不明确

C++: Ambiguos function call even with unique function names at each inheritence level

代码-

#include<iostream>
              
    using namespace std;
         
class P {
    public:
    void print()  { cout <<" Inside P"; }
    };
          
class Q : public P {
    public:
    void print() { cout <<" Inside Q"; }
    };
         
class Q2: public P {
    public:
    void print2() { cout <<" Inside Q2"; }
    };
          
class R: public Q2, public Q { };
          
int main(void)
{
    R r; 
    r.print(); // error: request for member ‘print’ is ambiguous
    return 0;
}

预期行为: main 中的第 3 行没有模棱两可的调用。

实际行为: main 中第 3 行的调用不明确

基本原理: 我希望 class Q 隐藏 class P 的 print() 函数。当 Q2 有与 R 或 Q(甚至 P?)相同的函数名称。但是我特意把Q2中的函数名改成了'print2'来避免这个错误。当我删除 'Q2' 作为 R 的父 class 时,此错误消失了。发生这种情况是因为 'Q2' 从 'P' 继承了 'print'?

注意:我知道在从多个 classes 继承的情况下,关于常规继承和模糊调用的数据隐藏已经提出了类似的问题,但这种情况是两者兼而有之,我没有找到任何具体答案。

I expected class Q to hide the print() function of class P

这与 Q 隐藏超类的 print() 无关。

Q2继承自P,因此继承了print().

class R: public Q2, public Q { };

print() 是从 Q2 和 Q 继承的。它们是相同的还是不同的方法并不重要。关键是 print() 方法 R.print() 解析为哪个是不明确的。

would expect an ambiguous call error when Q2 has the same function name

但确实如此。它继承了它。

这是非常典型的具有多重继承的 C++ Diamond problem

你所拥有的是当 R 调用他不知道从哪个打印到 cal 的打印函数时。

您可以通过帮助 R class 对象指定要调用的打印来解决此问题。

下面的修改可以说明这一点。

#include<iostream>
              
    using namespace std;
         
class P {
    public:
    void print()  { cout <<" Inside P\n"; }
    };
          
class Q : public P {
    public:
    void print() { cout <<" Inside Q\n"; }
    };
         
class Q2: public P {
    public:
    void print2() { cout <<" Inside Q2\n"; }
    };
          
class R: public Q2, public Q { };
          
int main(void)
{
    R r; 
    r.Q::print(); 
    r.Q2::print();
    // r.P::print();  ambiguous base call.
    // r.print();     ambiguous member
    return 0;
}