📜  C++ 中的继承歧义

📅  最后修改于: 2022-05-13 01:55:31.193000             🧑  作者: Mango

C++ 中的继承歧义

先决条件:C++ 中的继承、C++ 中的多重继承

在多重继承中,当一个类派生于两个或多个基类时,基类可能具有同名的函数,而派生类可能没有与其基类同名的函数。如果派生类对象需要访问基类的类似名称的成员函数之一,则会导致歧义,因为编译器会混淆应该调用哪个基类的类成员函数。

示例

C++
// C++ program to show inheritance ambiguity
  
#include
using namespace std;
  
// Base class A
  
class A {
    public:
  
    void func() {
        cout << " I am in class A" << endl;
    }
};
  
// Base class B
  
class B {
    public:
  
    void func() {
        cout << " I am in class B" << endl;
    }
};
  
// Derived class C
  
class C: public A, public B {
  
  
};
  
// Driver Code
  
int main() {
  
    // Created an object of class C
  
    C obj;
  
    // Calling function func()
  
    obj.func();
    
    return 0;
}


C++
// C++ program to resolve inheritance
// ambiguity
  
#include
using namespace std;
  
// Base class A
  
class A {
    public:
  
    void func() {
        cout << " I am in class A" << endl;
    }
};
  
// Base class B
  
class B {
    public:
  
    void func() {
        cout << " I am in class B" << endl;
    }
};
  
// Derived class C
class C: public A, public B {
  
  
};
  
// Driver Code
  
int main() {
  
    // Created an object of class C
    C obj;
  
    // Calling function func() in class A
    obj.A::func();
  
    // Calling function func() in class B
    obj.B::func();
  
    return 0;
}


C++
// C++ program to show function/method overriding
  
#include
using namespace std;
  
// Base class A
  
class A {
    public:
  
    void func() {
        cout << " I am in class A" << endl;
    }
};
  
// Base class B
class B {
    public:
  
    void func() {
        cout << " I am in class B" << endl;
    }
};
  
// Derived class C
class C: public A, public B {
    public:
    
    // Function overriding
    void func() {
        cout << " I am in class C" << endl;
    }
};
  
// Driver Code
  
int main() {
  
    // Created an object of class C
    C obj;
  
    // Calling function func() in class C
    // through scope resolution operator
    obj.C::func();
  
    // Calling function func() in class C
    // by default by compiler because of
    // method or function overriding
    obj.func();
  
    return 0;
}


输出

prog.cpp: In function ‘int main()’:
prog.cpp:43:9: error: request for member ‘func’ is ambiguous
     obj.func();
         ^
prog.cpp:21:10: note: candidates are: void B::func()
     void func() {
          ^
prog.cpp:11:10: note:                 void A::func()
     void func() {
          ^

在此示例中,派生类 C 继承了具有相同函数名称 func() 的两个基类 A 和 B。当创建类 C 的对象并调用函数func() 时,编译器会混淆应该调用哪个基类成员函数func()。

歧义的解决方案:

为了解决这种歧义,范围解析运算符使用' :: '表示

句法:

ObjectName.ClassName::FunctionName();

下面是显示多继承中歧义解决概念的程序。

C++

// C++ program to resolve inheritance
// ambiguity
  
#include
using namespace std;
  
// Base class A
  
class A {
    public:
  
    void func() {
        cout << " I am in class A" << endl;
    }
};
  
// Base class B
  
class B {
    public:
  
    void func() {
        cout << " I am in class B" << endl;
    }
};
  
// Derived class C
class C: public A, public B {
  
  
};
  
// Driver Code
  
int main() {
  
    // Created an object of class C
    C obj;
  
    // Calling function func() in class A
    obj.A::func();
  
    // Calling function func() in class B
    obj.B::func();
  
    return 0;
}
输出
I am in class A
 I am in class B

代码片段

  • 我们创建了一个由公共成员函数“func”组成的“A”类。
  • 我们创建了一个“B”类,它也包含公共成员函数“func”。
  • 我们创建了一个继承“A”和“B”类的“C”类。
  • 对象“obj”是由派生类“C”创建的。
  • 函数“func”由对象“obj”调用。

这里需要注意的重要一点是,当函数“func”被对象“obj”第一次调用时,它会调用“A”类的函数“func”,而当函数“func”被对象调用时“obj”第二次将调用“B”类的函数“func”,因为我们已使用范围解析运算符“::”指定它以消除歧义。

函数覆盖或方法覆盖

C++

// C++ program to show function/method overriding
  
#include
using namespace std;
  
// Base class A
  
class A {
    public:
  
    void func() {
        cout << " I am in class A" << endl;
    }
};
  
// Base class B
class B {
    public:
  
    void func() {
        cout << " I am in class B" << endl;
    }
};
  
// Derived class C
class C: public A, public B {
    public:
    
    // Function overriding
    void func() {
        cout << " I am in class C" << endl;
    }
};
  
// Driver Code
  
int main() {
  
    // Created an object of class C
    C obj;
  
    // Calling function func() in class C
    // through scope resolution operator
    obj.C::func();
  
    // Calling function func() in class C
    // by default by compiler because of
    // method or function overriding
    obj.func();
  
    return 0;
}
输出
I am in class C
 I am in class C

在这个例子中,我们可以看到我们也在派生类“C”中声明了函数func()。因此,当创建类“C”的对象并调用函数func() 时,会打印“I am in class C”,因为它会因为函数/方法覆盖而覆盖基类“func”方法。现在,如果我们不指定必须通过范围解析运算符调用哪个类成员函数“func”,那么默认情况下,编译器会运行编写在类主体中的方法,通过该方法创建对象的实例。但是,如果派生类“C”中不存在函数“func”,那么为了调用类“A”或“B”中的函数“func”,我们必须通过范围解析运算符指定它。因此,编译器将运行指定类的方法。