Minimal example:
class A {};
class B : public virtual A {};
class C : public virtual B {};
// define two overloading virtual functions
// no inheritance, so no overriding/hiding in this class
struct visitor1
{
virtual void visit(A& ) {}
virtual void visit(B& ) {}
virtual ~visitor1();
};
// covariant types are not allowed for overriding virtuals,
// so the C-visit function would hide A and B, so we add them
// using the "using" keyword
struct visitor2 : public visitor1
{
using visitor1::visit;
virtual void visit(C& ) {}
virtual ~visitor2();
};
// the B-visit is a correct override
// without the use of "using" (or the C-visit) below, the
// compiler warns that the C-visit function from visitor3
// is being overridden
struct visitor3 final : public visitor2
{
//using visitor2::visit;
//void visit(C &) override {}
void visit(B &) override {}
};
Compiler:
$ clang++ -Wall -Wextra -Weverything -Wno-c++98-compat visitor.cpp
visitor.cpp:32:14: warning: 'visitor3::visit' hides overloaded virtual function [-Woverloaded-virtual]
void visit(B &) override {}
^
visitor.cpp:20:22: note: hidden overloaded virtual function 'visitor2::visit' declared here: type mismatch at 1st parameter ('C &' vs 'B &')
virtual void visit(C& ) {}
^
Question (assuming the commented lines from visitor3 stay commented):
visitor3::visit(B&)
is hiding visitor2::visit(C&)
?visitor3::visit(B&)
is hiding visitor1::visit(A&)
(what's different here)?Additional question: How do I achieve that both visitor2::visit(C&)
and visitor1::visit(A&)
are not hidden in visitor3
? Does using visitor2::visit;
in visitor3
suffice?
The declaration of void visit(B&)
or any declaration a member named visit
(it could have been a data member int visit;
) in visitor3
hides any member of a parent called visit
.
Here the warning of the compiler is more a goodies. It recognized a common mistake pattern which consists in overriding a base virtual member function without taking care over of overloads. But it does not detect all hidden names, or does not warn for all of them. Whatsoever, all visit
from visitor1
and visitor2
are hidden.
Additional answer: The using declaration that name members of a base class is a declaration inside the derived class of all the members in the base class that have that name and are visible. So this effectively include members that where also declared by a using declaration in the base class.
(These members declared by a using declaration behave closely as if they were actual members first declared in that class. Even overload resolution considers their implied object parameter to be of the type of the derived class.)