“hidden overloaded virtual function” with more than 2 classes












1















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 hiding visitor2::visit(C&)?

  • Why does it not complain that 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?










share|improve this question

























  • 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
















1















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 hiding visitor2::visit(C&)?

  • Why does it not complain that 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?










share|improve this question

























  • 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














1












1








1








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 hiding visitor2::visit(C&)?

  • Why does it not complain that 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?










share|improve this question
















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 hiding visitor2::visit(C&)?

  • Why does it not complain that 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?







c++ overloading name-hiding






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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



















  • 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

















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












2 Answers
2






active

oldest

votes


















1














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.)






share|improve this answer


























  • "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











  • @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



















1














"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.






share|improve this answer
























  • 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











  • 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













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
});


}
});














draft saved

draft discarded


















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









1














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.)






share|improve this answer


























  • "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











  • @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
















1














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.)






share|improve this answer


























  • "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











  • @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














1












1








1







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.)






share|improve this answer















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.)







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 24 '18 at 15:58

























answered Nov 24 '18 at 12:42









OlivOliv

9,3421957




9,3421957













  • "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











  • @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











  • 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













1














"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.






share|improve this answer
























  • 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











  • 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


















1














"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.






share|improve this answer
























  • 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











  • 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
















1












1








1







"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.






share|improve this answer













"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.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 24 '18 at 13:21









Pete BeckerPete Becker

58.2k442119




58.2k442119













  • 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











  • 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





















  • 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











  • 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



















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




















draft saved

draft discarded




















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

Costa Masnaga

Fotorealismo

Sidney Franklin