Names of class members have the following properties:
- The name - an unqualified identifier.
- The declarative region - which class the name was declared in.
- The access - rights of the name within that region.
This applies to the names themselves -- not to any variable or function that a name refers to. It is possible to have the same function or variable named by the same name but in a different declarative region.
When a class is inherited, the derived class's declarative region includes all names from the base class; but the access may be changed based on the type of inheritance: although it's only possible to declare a member as public
, protected
, or private
, after inheritance you can end up with a member having no access.
Here is a table of accessability of names and regions in your code:

Note how tellName
is public in all three classes, despite the fact that it was not redeclared in Designer
. Accordingly, the ELayer
's using Employee::tellName;
is redundant because tellName
would have been public
in ELayer
anyway.
The effect of ELayer
's using Employee::showEveryDept;
is that showEveryDept
's access within ELayer
is private
.
Name Lookup is the process of resolving which name-region combination is found by a call to a name. The context of this call includes:
- The call site, i.e. the scope in which the name was used
- Any explicitly-listed scope in the call (e.g.
Foo::name
)
- The expression denoting object whose member is being accessed (e.g.
(*E)
)
Access control also takes into account:
- The relationship between the calling context and the declarative region in which the name was found.
For example, looking up showEveryDept
in the context of ELayer
will find the combination ELayer::showEveryDept
with access private
.
But looking up the same name in the context of Employee
will find the combination Employee::showEveryDept
which has access public
.
This behaviour is the same whether or not those two combinations refer to the same function.
Without reproducing the full list of rules about how the calling context translates to which declarative regions are searched, the usage:
`E->showEveryDept`
looks up the name in the region of the static type of *E
, which is Employee
. It does not use the dynamic type, because name lookup is resolved at compile-time. There are no run-time access errors -- access is a compile-time property.
The final step of the access check is to compare public
and Employee
with the call site, which is main()
. The rule is that public
grants access to all call sites, so the access check passes.
virtual-ness does not depend on the properties of names, nor the scope in which the name is being looked up. Unlike access, being virtual is a property of the function, not of any name-region combinations.
When virtual dispatch is active, calling a function will redirect the call to the final overrider of that function.
It's important to keep thinking of this in terms of function implementations - not of names for the functions. Virtual dispatch and Access Control are two completely separate operations.
Virtual dispatch is active only when a virtual function is called by an unqualified-id, which means by naming the function without Bla::
on the front.
So, in your code, E->showEveryDept
does activate virtual dispatch. The access check passes as described above, and then virtual dispatch invokes the final overrider, which happens to be the body defined in Employee
in this example.
In your actual example, virtual
is moot since the function is not overridden. But even if you had overridden showEveryDept
as a private function in ELayer
(instead of the using
declaration), it would still call that function body.