“hidden overloaded virtual function” with more than 2 classes
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):
- Why does the compiler complain that the
visitor3::visit(B&)
is hidingvisitor2::visit(C&)
? - Why does it not complain that
visitor3::visit(B&)
is hidingvisitor1::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?
c++ overloading name-hiding
add a comment |
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):
- Why does the compiler complain that the
visitor3::visit(B&)
is hidingvisitor2::visit(C&)
? - Why does it not complain that
visitor3::visit(B&)
is hidingvisitor1::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?
c++ overloading name-hiding
What happens if you declare avisit(B&)
?
– Matthieu Brucher
Nov 24 '18 at 12:15
@MatthieuBrucher If you mean declaring it invisitor2
, the error vanishes. In other classes, it's already declared.
– Johannes
Nov 24 '18 at 12:17
add a comment |
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):
- Why does the compiler complain that the
visitor3::visit(B&)
is hidingvisitor2::visit(C&)
? - Why does it not complain that
visitor3::visit(B&)
is hidingvisitor1::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?
c++ overloading name-hiding
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):
- Why does the compiler complain that the
visitor3::visit(B&)
is hidingvisitor2::visit(C&)
? - Why does it not complain that
visitor3::visit(B&)
is hidingvisitor1::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?
c++ overloading name-hiding
c++ overloading name-hiding
edited Nov 24 '18 at 12:54
Johannes
asked Nov 24 '18 at 12:13
JohannesJohannes
1,22931536
1,22931536
What happens if you declare avisit(B&)
?
– Matthieu Brucher
Nov 24 '18 at 12:15
@MatthieuBrucher If you mean declaring it invisitor2
, the error vanishes. In other classes, it's already declared.
– Johannes
Nov 24 '18 at 12:17
add a comment |
What happens if you declare avisit(B&)
?
– Matthieu Brucher
Nov 24 '18 at 12:15
@MatthieuBrucher If you mean declaring it invisitor2
, the error vanishes. In other classes, it's already declared.
– Johannes
Nov 24 '18 at 12:17
What happens if you declare a
visit(B&)
?– Matthieu Brucher
Nov 24 '18 at 12:15
What happens if you declare a
visit(B&)
?– Matthieu Brucher
Nov 24 '18 at 12:15
@MatthieuBrucher If you mean declaring it in
visitor2
, the error vanishes. In other classes, it's already declared.– Johannes
Nov 24 '18 at 12:17
@MatthieuBrucher If you mean declaring it in
visitor2
, the error vanishes. In other classes, it's already declared.– Johannes
Nov 24 '18 at 12:17
add a comment |
2 Answers
2
active
oldest
votes
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.)
"The declaration ofvoid visit(B&)
or ... hides any member of a parent called visit" -> Just to be sure, is it even true in case that declaration is just an overload? For the last sentence: "all visit from visitor 1 and visitor2 are hidden" -> Isvisitor1::visit(B&)
also hidden, or is it only overloaded?
– Johannes
Nov 24 '18 at 13:05
Also, can you please help me with the "additional question" that I just added?
– Johannes
Nov 24 '18 at 13:06
@Johannes I added it.
– Oliv
Nov 24 '18 at 15:57
Many thanks. I would not have guessed that the compiler does not detect all hidden names, and the answer makes that clear.
– Johannes
Nov 24 '18 at 17:00
add a comment |
"Hiding" is shorthand for what's really going on. The rule is simple (<g>): when looking up a name, the compiler starts in the current scope; if it finds that name, it's done. If it doesn't find it, it moves to the next enclosing scope. Repeat until done.
Couple that with the rule that overloading occurs only among functions defined in the same scope. Once the compiler finds that name, all definitions in the same scope participate in overloading. The compiler doesn't look in outer scopes to find things that might match the name. That way lies madness.
Note that name lookup looks only for the name; it does not depend on whether the name that's found overrides a name in the base class, nor on whether there is more than one function with the same name in the current scope (i.e., the name is overloaded). Once the name is found the search ends. All definitions of that name in that scope participate in overloading.
So, void visit(B&)
in visitor3
hides all of the other definitions of visit
in all of the base classes. The name is defined in visitor3
, so the compiler doesn't look anywhere else.
Let's change the code sovisitor3
inherits fromvisitor1
only (struct visitor3 : public visitor1
) (and change nothing else) and follow your answer. Now,visitor3::visit(B&)
is not overloadingvisitor1::visit(A&)
("no overloading in the same scope"), so it should hidevisitor::visit(A&)
, correct? Why does the compiler not warn me of hiding then?
– Johannes
Nov 24 '18 at 14:04
I don't know (or care) why the compiler doesn't warn you about your legal and well-defined code. Changing the base class doesn't change the fact thatvisitor3
has a definition ofvisit
, so the compiler doesn't look at the base class for other definitions.
– Pete Becker
Nov 24 '18 at 14:18
Maybe it thinks that in that simple case (inheriting once and just overloading one function with exactly the same signature), it's obvious and I know what I'm doing (hidingvisitor1::visit(B&)
)?
– Johannes
Nov 24 '18 at 14:24
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53458030%2fhidden-overloaded-virtual-function-with-more-than-2-classes%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
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.)
"The declaration ofvoid visit(B&)
or ... hides any member of a parent called visit" -> Just to be sure, is it even true in case that declaration is just an overload? For the last sentence: "all visit from visitor 1 and visitor2 are hidden" -> Isvisitor1::visit(B&)
also hidden, or is it only overloaded?
– Johannes
Nov 24 '18 at 13:05
Also, can you please help me with the "additional question" that I just added?
– Johannes
Nov 24 '18 at 13:06
@Johannes I added it.
– Oliv
Nov 24 '18 at 15:57
Many thanks. I would not have guessed that the compiler does not detect all hidden names, and the answer makes that clear.
– Johannes
Nov 24 '18 at 17:00
add a comment |
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.)
"The declaration ofvoid visit(B&)
or ... hides any member of a parent called visit" -> Just to be sure, is it even true in case that declaration is just an overload? For the last sentence: "all visit from visitor 1 and visitor2 are hidden" -> Isvisitor1::visit(B&)
also hidden, or is it only overloaded?
– Johannes
Nov 24 '18 at 13:05
Also, can you please help me with the "additional question" that I just added?
– Johannes
Nov 24 '18 at 13:06
@Johannes I added it.
– Oliv
Nov 24 '18 at 15:57
Many thanks. I would not have guessed that the compiler does not detect all hidden names, and the answer makes that clear.
– Johannes
Nov 24 '18 at 17:00
add a comment |
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.)
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.)
edited Nov 24 '18 at 15:58
answered Nov 24 '18 at 12:42
OlivOliv
9,3421957
9,3421957
"The declaration ofvoid visit(B&)
or ... hides any member of a parent called visit" -> Just to be sure, is it even true in case that declaration is just an overload? For the last sentence: "all visit from visitor 1 and visitor2 are hidden" -> Isvisitor1::visit(B&)
also hidden, or is it only overloaded?
– Johannes
Nov 24 '18 at 13:05
Also, can you please help me with the "additional question" that I just added?
– Johannes
Nov 24 '18 at 13:06
@Johannes I added it.
– Oliv
Nov 24 '18 at 15:57
Many thanks. I would not have guessed that the compiler does not detect all hidden names, and the answer makes that clear.
– Johannes
Nov 24 '18 at 17:00
add a comment |
"The declaration ofvoid visit(B&)
or ... hides any member of a parent called visit" -> Just to be sure, is it even true in case that declaration is just an overload? For the last sentence: "all visit from visitor 1 and visitor2 are hidden" -> Isvisitor1::visit(B&)
also hidden, or is it only overloaded?
– Johannes
Nov 24 '18 at 13:05
Also, can you please help me with the "additional question" that I just added?
– Johannes
Nov 24 '18 at 13:06
@Johannes I added it.
– Oliv
Nov 24 '18 at 15:57
Many thanks. I would not have guessed that the compiler does not detect all hidden names, and the answer makes that clear.
– Johannes
Nov 24 '18 at 17:00
"The declaration of
void visit(B&)
or ... hides any member of a parent called visit" -> Just to be sure, is it even true in case that declaration is just an overload? For the last sentence: "all visit from visitor 1 and visitor2 are hidden" -> Is visitor1::visit(B&)
also hidden, or is it only overloaded?– Johannes
Nov 24 '18 at 13:05
"The declaration of
void visit(B&)
or ... hides any member of a parent called visit" -> Just to be sure, is it even true in case that declaration is just an overload? For the last sentence: "all visit from visitor 1 and visitor2 are hidden" -> Is visitor1::visit(B&)
also hidden, or is it only overloaded?– Johannes
Nov 24 '18 at 13:05
Also, can you please help me with the "additional question" that I just added?
– Johannes
Nov 24 '18 at 13:06
Also, can you please help me with the "additional question" that I just added?
– Johannes
Nov 24 '18 at 13:06
@Johannes I added it.
– Oliv
Nov 24 '18 at 15:57
@Johannes I added it.
– Oliv
Nov 24 '18 at 15:57
Many thanks. I would not have guessed that the compiler does not detect all hidden names, and the answer makes that clear.
– Johannes
Nov 24 '18 at 17:00
Many thanks. I would not have guessed that the compiler does not detect all hidden names, and the answer makes that clear.
– Johannes
Nov 24 '18 at 17:00
add a comment |
"Hiding" is shorthand for what's really going on. The rule is simple (<g>): when looking up a name, the compiler starts in the current scope; if it finds that name, it's done. If it doesn't find it, it moves to the next enclosing scope. Repeat until done.
Couple that with the rule that overloading occurs only among functions defined in the same scope. Once the compiler finds that name, all definitions in the same scope participate in overloading. The compiler doesn't look in outer scopes to find things that might match the name. That way lies madness.
Note that name lookup looks only for the name; it does not depend on whether the name that's found overrides a name in the base class, nor on whether there is more than one function with the same name in the current scope (i.e., the name is overloaded). Once the name is found the search ends. All definitions of that name in that scope participate in overloading.
So, void visit(B&)
in visitor3
hides all of the other definitions of visit
in all of the base classes. The name is defined in visitor3
, so the compiler doesn't look anywhere else.
Let's change the code sovisitor3
inherits fromvisitor1
only (struct visitor3 : public visitor1
) (and change nothing else) and follow your answer. Now,visitor3::visit(B&)
is not overloadingvisitor1::visit(A&)
("no overloading in the same scope"), so it should hidevisitor::visit(A&)
, correct? Why does the compiler not warn me of hiding then?
– Johannes
Nov 24 '18 at 14:04
I don't know (or care) why the compiler doesn't warn you about your legal and well-defined code. Changing the base class doesn't change the fact thatvisitor3
has a definition ofvisit
, so the compiler doesn't look at the base class for other definitions.
– Pete Becker
Nov 24 '18 at 14:18
Maybe it thinks that in that simple case (inheriting once and just overloading one function with exactly the same signature), it's obvious and I know what I'm doing (hidingvisitor1::visit(B&)
)?
– Johannes
Nov 24 '18 at 14:24
add a comment |
"Hiding" is shorthand for what's really going on. The rule is simple (<g>): when looking up a name, the compiler starts in the current scope; if it finds that name, it's done. If it doesn't find it, it moves to the next enclosing scope. Repeat until done.
Couple that with the rule that overloading occurs only among functions defined in the same scope. Once the compiler finds that name, all definitions in the same scope participate in overloading. The compiler doesn't look in outer scopes to find things that might match the name. That way lies madness.
Note that name lookup looks only for the name; it does not depend on whether the name that's found overrides a name in the base class, nor on whether there is more than one function with the same name in the current scope (i.e., the name is overloaded). Once the name is found the search ends. All definitions of that name in that scope participate in overloading.
So, void visit(B&)
in visitor3
hides all of the other definitions of visit
in all of the base classes. The name is defined in visitor3
, so the compiler doesn't look anywhere else.
Let's change the code sovisitor3
inherits fromvisitor1
only (struct visitor3 : public visitor1
) (and change nothing else) and follow your answer. Now,visitor3::visit(B&)
is not overloadingvisitor1::visit(A&)
("no overloading in the same scope"), so it should hidevisitor::visit(A&)
, correct? Why does the compiler not warn me of hiding then?
– Johannes
Nov 24 '18 at 14:04
I don't know (or care) why the compiler doesn't warn you about your legal and well-defined code. Changing the base class doesn't change the fact thatvisitor3
has a definition ofvisit
, so the compiler doesn't look at the base class for other definitions.
– Pete Becker
Nov 24 '18 at 14:18
Maybe it thinks that in that simple case (inheriting once and just overloading one function with exactly the same signature), it's obvious and I know what I'm doing (hidingvisitor1::visit(B&)
)?
– Johannes
Nov 24 '18 at 14:24
add a comment |
"Hiding" is shorthand for what's really going on. The rule is simple (<g>): when looking up a name, the compiler starts in the current scope; if it finds that name, it's done. If it doesn't find it, it moves to the next enclosing scope. Repeat until done.
Couple that with the rule that overloading occurs only among functions defined in the same scope. Once the compiler finds that name, all definitions in the same scope participate in overloading. The compiler doesn't look in outer scopes to find things that might match the name. That way lies madness.
Note that name lookup looks only for the name; it does not depend on whether the name that's found overrides a name in the base class, nor on whether there is more than one function with the same name in the current scope (i.e., the name is overloaded). Once the name is found the search ends. All definitions of that name in that scope participate in overloading.
So, void visit(B&)
in visitor3
hides all of the other definitions of visit
in all of the base classes. The name is defined in visitor3
, so the compiler doesn't look anywhere else.
"Hiding" is shorthand for what's really going on. The rule is simple (<g>): when looking up a name, the compiler starts in the current scope; if it finds that name, it's done. If it doesn't find it, it moves to the next enclosing scope. Repeat until done.
Couple that with the rule that overloading occurs only among functions defined in the same scope. Once the compiler finds that name, all definitions in the same scope participate in overloading. The compiler doesn't look in outer scopes to find things that might match the name. That way lies madness.
Note that name lookup looks only for the name; it does not depend on whether the name that's found overrides a name in the base class, nor on whether there is more than one function with the same name in the current scope (i.e., the name is overloaded). Once the name is found the search ends. All definitions of that name in that scope participate in overloading.
So, void visit(B&)
in visitor3
hides all of the other definitions of visit
in all of the base classes. The name is defined in visitor3
, so the compiler doesn't look anywhere else.
answered Nov 24 '18 at 13:21
Pete BeckerPete Becker
58.2k442119
58.2k442119
Let's change the code sovisitor3
inherits fromvisitor1
only (struct visitor3 : public visitor1
) (and change nothing else) and follow your answer. Now,visitor3::visit(B&)
is not overloadingvisitor1::visit(A&)
("no overloading in the same scope"), so it should hidevisitor::visit(A&)
, correct? Why does the compiler not warn me of hiding then?
– Johannes
Nov 24 '18 at 14:04
I don't know (or care) why the compiler doesn't warn you about your legal and well-defined code. Changing the base class doesn't change the fact thatvisitor3
has a definition ofvisit
, so the compiler doesn't look at the base class for other definitions.
– Pete Becker
Nov 24 '18 at 14:18
Maybe it thinks that in that simple case (inheriting once and just overloading one function with exactly the same signature), it's obvious and I know what I'm doing (hidingvisitor1::visit(B&)
)?
– Johannes
Nov 24 '18 at 14:24
add a comment |
Let's change the code sovisitor3
inherits fromvisitor1
only (struct visitor3 : public visitor1
) (and change nothing else) and follow your answer. Now,visitor3::visit(B&)
is not overloadingvisitor1::visit(A&)
("no overloading in the same scope"), so it should hidevisitor::visit(A&)
, correct? Why does the compiler not warn me of hiding then?
– Johannes
Nov 24 '18 at 14:04
I don't know (or care) why the compiler doesn't warn you about your legal and well-defined code. Changing the base class doesn't change the fact thatvisitor3
has a definition ofvisit
, so the compiler doesn't look at the base class for other definitions.
– Pete Becker
Nov 24 '18 at 14:18
Maybe it thinks that in that simple case (inheriting once and just overloading one function with exactly the same signature), it's obvious and I know what I'm doing (hidingvisitor1::visit(B&)
)?
– Johannes
Nov 24 '18 at 14:24
Let's change the code so
visitor3
inherits from visitor1
only (struct visitor3 : public visitor1
) (and change nothing else) and follow your answer. Now, visitor3::visit(B&)
is not overloading visitor1::visit(A&)
("no overloading in the same scope"), so it should hide visitor::visit(A&)
, correct? Why does the compiler not warn me of hiding then?– Johannes
Nov 24 '18 at 14:04
Let's change the code so
visitor3
inherits from visitor1
only (struct visitor3 : public visitor1
) (and change nothing else) and follow your answer. Now, visitor3::visit(B&)
is not overloading visitor1::visit(A&)
("no overloading in the same scope"), so it should hide visitor::visit(A&)
, correct? Why does the compiler not warn me of hiding then?– Johannes
Nov 24 '18 at 14:04
I don't know (or care) why the compiler doesn't warn you about your legal and well-defined code. Changing the base class doesn't change the fact that
visitor3
has a definition of visit
, so the compiler doesn't look at the base class for other definitions.– Pete Becker
Nov 24 '18 at 14:18
I don't know (or care) why the compiler doesn't warn you about your legal and well-defined code. Changing the base class doesn't change the fact that
visitor3
has a definition of visit
, so the compiler doesn't look at the base class for other definitions.– Pete Becker
Nov 24 '18 at 14:18
Maybe it thinks that in that simple case (inheriting once and just overloading one function with exactly the same signature), it's obvious and I know what I'm doing (hiding
visitor1::visit(B&)
)?– Johannes
Nov 24 '18 at 14:24
Maybe it thinks that in that simple case (inheriting once and just overloading one function with exactly the same signature), it's obvious and I know what I'm doing (hiding
visitor1::visit(B&)
)?– Johannes
Nov 24 '18 at 14:24
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53458030%2fhidden-overloaded-virtual-function-with-more-than-2-classes%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
What happens if you declare a
visit(B&)
?– Matthieu Brucher
Nov 24 '18 at 12:15
@MatthieuBrucher If you mean declaring it in
visitor2
, the error vanishes. In other classes, it's already declared.– Johannes
Nov 24 '18 at 12:17