Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Thinking in C++ Vol 2 - Practical Programming
Prev Home Next

Name lookup issues

The ambiguities we have illustrated with subobjects apply to any names, including function names. If a class has multiple direct base classes that share member functions of the same name, and you call one of those member functions, the compiler doesn t know which one to choose. The following sample program would report such an error:

//: C09:AmbiguousName.cpp {-xo}
 
class Top {
public:
virtual ~Top() {}
};
 
class Left : virtual public Top {
public:
void f() {}
};
 
class Right : virtual public Top {
public:
void f() {}
};
 
class Bottom : public Left, public Right {};
 
int main() {
Bottom b;
b.f(); // Error here
} ///:~
 

The class Bottom has inherited two functions of the same name (the signature is irrelevant, since name lookup occurs before overload resolution), and there is no way to choose between them. The usual technique to disambiguate the call is to qualify the function call with the base class name:

//: C09:BreakTie.cpp
 
class Top {
public:
virtual ~Top() {}
};
 
class Left : virtual public Top {
public:
void f() {}
};
 
class Right : virtual public Top {
public:
void f() {}
};
 
class Bottom : public Left, public Right {
public:
using Left::f;
};
 
int main() {
Bottom b;
b.f(); // Calls Left::f()
} ///:~
 

The name Left::f is now found in the scope of Bottom, so the name Right::f is not even considered. To introduce extra functionality beyond what Left::f( ) provides, you implement a Bottom::f( ) function that calls Left::f( ).

Functions with the same name occurring in different branches of a hierarchy often conflict. The following hierarchy has no such problem:

//: C09:Dominance.cpp
 
class Top {
public:
virtual ~Top() {}
virtual void f() {}
};
 
class Left : virtual public Top {
public:
void f() {}
};
 
class Right : virtual public Top {};
 
class Bottom : public Left, public Right {};
 
int main() {
Bottom b;
b.f(); // Calls Left::f()
} ///:~
 

Here, there is no explicit Right::f( ). Since Left::f( ) is the most derived, it is chosen. Why? Well, pretend that Right did not exist, giving the single-inheritance hierarchy Top <= Left <= Bottom. You would certainly expect Left::f( ) to be the function called by the expression b.f( ) because of normal scope rules: a derived class is considered a nested scope of a base class. In general, a name A::f dominates the name B::f if A derives from B, directly or indirectly, or in other words, if A is more derived in the hierarchy than B.[129] Therefore, in choosing between two functions with the same name, the compiler chooses the one that dominates. If there is no dominant name, there is an ambiguity.

The following program further illustrates the dominance principle:

//: C09:Dominance2.cpp
#include <iostream>
using namespace std;
 
class A {
public:
virtual ~A() {}
virtual void f() { cout << "A::f\n"; }
};
 
class B : virtual public A {
public:
void f() { cout << "B::f\n"; }
};
 
class C : public B {};
class D : public C, virtual public A {};
 
int main() {
B* p = new D;
p->f(); // Calls B::f()
delete p;
} ///:~
 

The class diagram for this hierarchy is

The class A is a (direct, in this case) base class for B, and so the name B::f dominates A::f.

Thinking in C++ Vol 2 - Practical Programming
Prev Home Next

 
 
   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire