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”,我们必须通过范围解析运算符指定它。因此,编译器将运行指定类的方法。