The logic of invoking virtual functions is not clear (or it is method hiding?)When to use virtual destructors?What is the performance cost of having a virtual method in a C++ class?Can I call a base class's virtual function if I'm overriding it?Calling virtual functions inside constructorsWhy do we need virtual functions in C++?C++: inheriting overloaded non-virtual method and virtual method both with the same name causes problemC++ “virtual” keyword for functions in derived classes. Is it necessary?Confusion regarding name hiding and virtual functionsIs the 'override' keyword just a check for a overridden virtual method?Virtual method being called instead of derived methodWhy does this virtual method return true?
Metal that glows when near pieces of itself
Would combining A* with a flocking algorithm be too performance-heavy?
Why didn’t Doctor Strange stay in the original winning timeline?
Importing ES6 module in LWC project (sfdx)
Overwrite file only if data
Why doesn't mathematics collapse even though humans quite often make mistakes in their proofs?
Are illustrations in novels frowned upon?
Can I submit a paper under an alias so as to avoid trouble in my country?
Why we don't have vaccination against all diseases which are caused by microbes?
Can you be convicted for being a murderer twice?
Can my boyfriend, who lives in the UK and has a Polish passport, visit me in the USA?
Why don't politicians push for fossil fuel reduction by pointing out their scarcity?
Don't understand MOSFET as amplifier
How do you call it when two celestial bodies come as close to each other as they will in their current orbits?
In an emergency, how do I find and share my position?
Is there a known non-euclidean geometry where two concentric circles of different radii can intersect? (as in the novel "The Universe Between")
How does turbine efficiency compare with internal combustion engines if all the turbine power is converted to mechanical energy?
Why don't we use Cavea-B
Sleeping solo in a double sleeping bag
How to persuade recruiters to send me the Job Description?
What is this shrub with berries?
The teacher logged me in as administrator for doing a short task, is the whole system now compromised?
Defense against attacks using dictionaries
Co-author responds to email by mistake cc'ing the EiC
The logic of invoking virtual functions is not clear (or it is method hiding?)
When to use virtual destructors?What is the performance cost of having a virtual method in a C++ class?Can I call a base class's virtual function if I'm overriding it?Calling virtual functions inside constructorsWhy do we need virtual functions in C++?C++: inheriting overloaded non-virtual method and virtual method both with the same name causes problemC++ “virtual” keyword for functions in derived classes. Is it necessary?Confusion regarding name hiding and virtual functionsIs the 'override' keyword just a check for a overridden virtual method?Virtual method being called instead of derived methodWhy does this virtual method return true?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
(tested on msvc2017)
struct AAA
virtual float run(int arg)
return 5.5f;
;
struct BBB : AAA
virtual bool run(double arg)
return false;
;
struct CCC : BBB
virtual float run(int arg)
return 7.7f;
virtual bool run(double arg)
return true;
;
CCC c;
BBB* pb = &c;
pb->run(5); // call CCC::run(double arg), WHY??
pb->run((int)5); // call CCC::run(double arg), WHY??
Why does pb->run(5) call only CCC::run(double arg), but not CCC::run(int arg)?
Does the virtual method of a child class with a different signature overlap the interface of the base class?
c++ class inheritance overriding virtual
New contributor
dimasafo is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
add a comment |
(tested on msvc2017)
struct AAA
virtual float run(int arg)
return 5.5f;
;
struct BBB : AAA
virtual bool run(double arg)
return false;
;
struct CCC : BBB
virtual float run(int arg)
return 7.7f;
virtual bool run(double arg)
return true;
;
CCC c;
BBB* pb = &c;
pb->run(5); // call CCC::run(double arg), WHY??
pb->run((int)5); // call CCC::run(double arg), WHY??
Why does pb->run(5) call only CCC::run(double arg), but not CCC::run(int arg)?
Does the virtual method of a child class with a different signature overlap the interface of the base class?
c++ class inheritance overriding virtual
New contributor
dimasafo is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
1
You have misconceptions about function signatures and how these are matching, that's all. Voted to close.
– πάντα ῥεῖ
8 hours ago
8
@πάνταῥεῖ Close for what reason?
– melpomene
8 hours ago
This is not a question about signatures having to match for the virtual method in the derived class. It's phrased confusingly, but that's not what's asked here.
– Sam Varshavchik
8 hours ago
I'm sure we have a few name hiding dupes though
– Lightness Races in Orbit
7 hours ago
I understand! The call works because int can be implicitly converted to double. (otherwise it would cause compilation error) If we replace AAA::run(int) and CCC::run(int) to respectively AAA::run(CustomType) and CCC::run(CustomType) - it would cause compilation error
– dimasafo
7 hours ago
add a comment |
(tested on msvc2017)
struct AAA
virtual float run(int arg)
return 5.5f;
;
struct BBB : AAA
virtual bool run(double arg)
return false;
;
struct CCC : BBB
virtual float run(int arg)
return 7.7f;
virtual bool run(double arg)
return true;
;
CCC c;
BBB* pb = &c;
pb->run(5); // call CCC::run(double arg), WHY??
pb->run((int)5); // call CCC::run(double arg), WHY??
Why does pb->run(5) call only CCC::run(double arg), but not CCC::run(int arg)?
Does the virtual method of a child class with a different signature overlap the interface of the base class?
c++ class inheritance overriding virtual
New contributor
dimasafo is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
(tested on msvc2017)
struct AAA
virtual float run(int arg)
return 5.5f;
;
struct BBB : AAA
virtual bool run(double arg)
return false;
;
struct CCC : BBB
virtual float run(int arg)
return 7.7f;
virtual bool run(double arg)
return true;
;
CCC c;
BBB* pb = &c;
pb->run(5); // call CCC::run(double arg), WHY??
pb->run((int)5); // call CCC::run(double arg), WHY??
Why does pb->run(5) call only CCC::run(double arg), but not CCC::run(int arg)?
Does the virtual method of a child class with a different signature overlap the interface of the base class?
c++ class inheritance overriding virtual
c++ class inheritance overriding virtual
New contributor
dimasafo is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
dimasafo is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
edited 7 hours ago
Vlad from Moscow
150k14 gold badges92 silver badges192 bronze badges
150k14 gold badges92 silver badges192 bronze badges
New contributor
dimasafo is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
asked 8 hours ago
dimasafodimasafo
443 bronze badges
443 bronze badges
New contributor
dimasafo is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
dimasafo is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
1
You have misconceptions about function signatures and how these are matching, that's all. Voted to close.
– πάντα ῥεῖ
8 hours ago
8
@πάνταῥεῖ Close for what reason?
– melpomene
8 hours ago
This is not a question about signatures having to match for the virtual method in the derived class. It's phrased confusingly, but that's not what's asked here.
– Sam Varshavchik
8 hours ago
I'm sure we have a few name hiding dupes though
– Lightness Races in Orbit
7 hours ago
I understand! The call works because int can be implicitly converted to double. (otherwise it would cause compilation error) If we replace AAA::run(int) and CCC::run(int) to respectively AAA::run(CustomType) and CCC::run(CustomType) - it would cause compilation error
– dimasafo
7 hours ago
add a comment |
1
You have misconceptions about function signatures and how these are matching, that's all. Voted to close.
– πάντα ῥεῖ
8 hours ago
8
@πάνταῥεῖ Close for what reason?
– melpomene
8 hours ago
This is not a question about signatures having to match for the virtual method in the derived class. It's phrased confusingly, but that's not what's asked here.
– Sam Varshavchik
8 hours ago
I'm sure we have a few name hiding dupes though
– Lightness Races in Orbit
7 hours ago
I understand! The call works because int can be implicitly converted to double. (otherwise it would cause compilation error) If we replace AAA::run(int) and CCC::run(int) to respectively AAA::run(CustomType) and CCC::run(CustomType) - it would cause compilation error
– dimasafo
7 hours ago
1
1
You have misconceptions about function signatures and how these are matching, that's all. Voted to close.
– πάντα ῥεῖ
8 hours ago
You have misconceptions about function signatures and how these are matching, that's all. Voted to close.
– πάντα ῥεῖ
8 hours ago
8
8
@πάνταῥεῖ Close for what reason?
– melpomene
8 hours ago
@πάνταῥεῖ Close for what reason?
– melpomene
8 hours ago
This is not a question about signatures having to match for the virtual method in the derived class. It's phrased confusingly, but that's not what's asked here.
– Sam Varshavchik
8 hours ago
This is not a question about signatures having to match for the virtual method in the derived class. It's phrased confusingly, but that's not what's asked here.
– Sam Varshavchik
8 hours ago
I'm sure we have a few name hiding dupes though
– Lightness Races in Orbit
7 hours ago
I'm sure we have a few name hiding dupes though
– Lightness Races in Orbit
7 hours ago
I understand! The call works because int can be implicitly converted to double. (otherwise it would cause compilation error) If we replace AAA::run(int) and CCC::run(int) to respectively AAA::run(CustomType) and CCC::run(CustomType) - it would cause compilation error
– dimasafo
7 hours ago
I understand! The call works because int can be implicitly converted to double. (otherwise it would cause compilation error) If we replace AAA::run(int) and CCC::run(int) to respectively AAA::run(CustomType) and CCC::run(CustomType) - it would cause compilation error
– dimasafo
7 hours ago
add a comment |
2 Answers
2
active
oldest
votes
All is simple.
The class BBB has in fact two virtual functions. One is declared in its base class AAA
struct AAA
virtual float run(int arg)
return 5.5f;
;
And other is declared in the class BBB itself.
struct BBB : AAA
virtual bool run(double arg)
return false;
;
The function declared in the class BBB hides the function declared in the class AAA. (Any name declared in a derived class hides an entity with the same name declared in the base class of the derived class)
In the class CCC the both functions are overriden.
These function calls
pb->run(5); // call CCC::run(double arg), WHY??
pb->run((int)5); // call CCC::run(double arg), WHY??
do not differ because their arguments have the type int.
The static type of the pointer pb is BBB *. So the compiler searches the name run in the class BBB.
Within the class only one function with this name is visible. It is the function declared in the class
virtual bool run(double arg)
return false;
So the compiler runs this virtual function with this signature but invokes it using the table of virtual function pointers defined for the class CCC because the dynamic type of the pointer pb is CCC *.
You could make the function declared in the class AAA visible within the class BBB by means of the using declaration. For example
struct BBB : AAA
using AAA:: run;
virtual bool run(double arg)
return false;
;
In this case the declaration of the function (declared in the class AAA) would be also a member declaration inside the class BBB. That is the class BBB will have declarations of two overloaded distinct virtual functions.
Here is a demonstrative program
#include <iostream>
struct AAA
virtual float run(int arg)
return 5.5f;
;
struct BBB : AAA
using AAA:: run;
virtual bool run(double arg)
return false;
;
struct CCC : BBB
virtual float run(int arg)
return 7.7f;
virtual bool run(double arg)
return true;
;
int main()
CCC c;
BBB* pb = &c;
std::cout << pb->run(5) << 'n';
std::cout << pb->run(5.6 ) << 'n';
return 0;
Its output is
7.7
1
To make the situation with the member declarations in a derived class and in its base class consider a similar situation with block scopes.
Here is a demonstrative program
#include <iostream>
void f( int ) std::cout << "void f( int )n";
void f( double ) std::cout << "void f( double )n";
int main()
void f( double );
f( 5 );
f( 5.5 );
return 0;
The inner declaration of the function f in the block scope of the function main hides the other declaration of the function in the global scope.
The program output is
void f( double )
void f( double )
@LightnessRacesinOrbit Thanks. I updated the post.
– Vlad from Moscow
7 hours ago
>>So the compiler searches the name run in the class BBB. Does it mean than compiler searches only by name but not with full prototype?
– dimasafo
7 hours ago
2
@dimasafo It searches the name. Then it determines that the name belongs to a function and uses the function declaration to call its corresponding definition that is overriden in the class CCC.
– Vlad from Moscow
7 hours ago
add a comment |
When you do
struct BBB : AAA
virtual bool run(double arg)
return false;
;
run has a different signature from run in AAA. This means that BBB::run(double) will hide AAA::run(int). Since it does, the only run that you can call from BBB is bool run(double arg). When you do
pb->run(5);
it finds bool BBB::run(double arg) as that is the only function you can call statically from a BBB and then virtual dispatch kicks in calling CCC::run(double)
In order to get the int version of the function to be called, you need to bring the int version into BBB. You can do this by writing one, or you could use using AAA::run; to import it in. Doing either of those will make pb->run(5); call the int version of run from CCC.
Don't forget, when playing with polymorphism you should declare the top level destructor (AAA's in this case) to be virtual. This allows you to delete objects correctly when using dynamic allocation. For full details see: When to use virtual destructors?
>>This means that BBB::run(double) will hide AAA::run(int) I thought it will hide medhod only for BBB but not for CCC. In fact it is unclear for me. So the vtable will contain only one function. Right?
– dimasafo
8 hours ago
@JeJo: Through anAAA*, you would findfloat run(int)(and only that one, no possibility to callbool run(double))
– Ben Voigt
8 hours ago
@dimasafo Can't say about that. The reason theintversion isn't called is becauseBBBcan only callBBB::run(double), so that is the fucntion that virtual dispatch happens on. Theintversion is never considered.
– NathanOliver
8 hours ago
@dimasafopbis aBBB, so onlyBBB's functions are considered. If you changepbto be aAAA*then theintversion is called.
– NathanOliver
8 hours ago
1
Feels like usingoverridehere would have helped out a lot.
– François Andrieux
7 hours ago
|
show 1 more 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
);
);
dimasafo is a new contributor. Be nice, and check out our Code of Conduct.
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%2f57577757%2fthe-logic-of-invoking-virtual-functions-is-not-clear-or-it-is-method-hiding%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
All is simple.
The class BBB has in fact two virtual functions. One is declared in its base class AAA
struct AAA
virtual float run(int arg)
return 5.5f;
;
And other is declared in the class BBB itself.
struct BBB : AAA
virtual bool run(double arg)
return false;
;
The function declared in the class BBB hides the function declared in the class AAA. (Any name declared in a derived class hides an entity with the same name declared in the base class of the derived class)
In the class CCC the both functions are overriden.
These function calls
pb->run(5); // call CCC::run(double arg), WHY??
pb->run((int)5); // call CCC::run(double arg), WHY??
do not differ because their arguments have the type int.
The static type of the pointer pb is BBB *. So the compiler searches the name run in the class BBB.
Within the class only one function with this name is visible. It is the function declared in the class
virtual bool run(double arg)
return false;
So the compiler runs this virtual function with this signature but invokes it using the table of virtual function pointers defined for the class CCC because the dynamic type of the pointer pb is CCC *.
You could make the function declared in the class AAA visible within the class BBB by means of the using declaration. For example
struct BBB : AAA
using AAA:: run;
virtual bool run(double arg)
return false;
;
In this case the declaration of the function (declared in the class AAA) would be also a member declaration inside the class BBB. That is the class BBB will have declarations of two overloaded distinct virtual functions.
Here is a demonstrative program
#include <iostream>
struct AAA
virtual float run(int arg)
return 5.5f;
;
struct BBB : AAA
using AAA:: run;
virtual bool run(double arg)
return false;
;
struct CCC : BBB
virtual float run(int arg)
return 7.7f;
virtual bool run(double arg)
return true;
;
int main()
CCC c;
BBB* pb = &c;
std::cout << pb->run(5) << 'n';
std::cout << pb->run(5.6 ) << 'n';
return 0;
Its output is
7.7
1
To make the situation with the member declarations in a derived class and in its base class consider a similar situation with block scopes.
Here is a demonstrative program
#include <iostream>
void f( int ) std::cout << "void f( int )n";
void f( double ) std::cout << "void f( double )n";
int main()
void f( double );
f( 5 );
f( 5.5 );
return 0;
The inner declaration of the function f in the block scope of the function main hides the other declaration of the function in the global scope.
The program output is
void f( double )
void f( double )
@LightnessRacesinOrbit Thanks. I updated the post.
– Vlad from Moscow
7 hours ago
>>So the compiler searches the name run in the class BBB. Does it mean than compiler searches only by name but not with full prototype?
– dimasafo
7 hours ago
2
@dimasafo It searches the name. Then it determines that the name belongs to a function and uses the function declaration to call its corresponding definition that is overriden in the class CCC.
– Vlad from Moscow
7 hours ago
add a comment |
All is simple.
The class BBB has in fact two virtual functions. One is declared in its base class AAA
struct AAA
virtual float run(int arg)
return 5.5f;
;
And other is declared in the class BBB itself.
struct BBB : AAA
virtual bool run(double arg)
return false;
;
The function declared in the class BBB hides the function declared in the class AAA. (Any name declared in a derived class hides an entity with the same name declared in the base class of the derived class)
In the class CCC the both functions are overriden.
These function calls
pb->run(5); // call CCC::run(double arg), WHY??
pb->run((int)5); // call CCC::run(double arg), WHY??
do not differ because their arguments have the type int.
The static type of the pointer pb is BBB *. So the compiler searches the name run in the class BBB.
Within the class only one function with this name is visible. It is the function declared in the class
virtual bool run(double arg)
return false;
So the compiler runs this virtual function with this signature but invokes it using the table of virtual function pointers defined for the class CCC because the dynamic type of the pointer pb is CCC *.
You could make the function declared in the class AAA visible within the class BBB by means of the using declaration. For example
struct BBB : AAA
using AAA:: run;
virtual bool run(double arg)
return false;
;
In this case the declaration of the function (declared in the class AAA) would be also a member declaration inside the class BBB. That is the class BBB will have declarations of two overloaded distinct virtual functions.
Here is a demonstrative program
#include <iostream>
struct AAA
virtual float run(int arg)
return 5.5f;
;
struct BBB : AAA
using AAA:: run;
virtual bool run(double arg)
return false;
;
struct CCC : BBB
virtual float run(int arg)
return 7.7f;
virtual bool run(double arg)
return true;
;
int main()
CCC c;
BBB* pb = &c;
std::cout << pb->run(5) << 'n';
std::cout << pb->run(5.6 ) << 'n';
return 0;
Its output is
7.7
1
To make the situation with the member declarations in a derived class and in its base class consider a similar situation with block scopes.
Here is a demonstrative program
#include <iostream>
void f( int ) std::cout << "void f( int )n";
void f( double ) std::cout << "void f( double )n";
int main()
void f( double );
f( 5 );
f( 5.5 );
return 0;
The inner declaration of the function f in the block scope of the function main hides the other declaration of the function in the global scope.
The program output is
void f( double )
void f( double )
@LightnessRacesinOrbit Thanks. I updated the post.
– Vlad from Moscow
7 hours ago
>>So the compiler searches the name run in the class BBB. Does it mean than compiler searches only by name but not with full prototype?
– dimasafo
7 hours ago
2
@dimasafo It searches the name. Then it determines that the name belongs to a function and uses the function declaration to call its corresponding definition that is overriden in the class CCC.
– Vlad from Moscow
7 hours ago
add a comment |
All is simple.
The class BBB has in fact two virtual functions. One is declared in its base class AAA
struct AAA
virtual float run(int arg)
return 5.5f;
;
And other is declared in the class BBB itself.
struct BBB : AAA
virtual bool run(double arg)
return false;
;
The function declared in the class BBB hides the function declared in the class AAA. (Any name declared in a derived class hides an entity with the same name declared in the base class of the derived class)
In the class CCC the both functions are overriden.
These function calls
pb->run(5); // call CCC::run(double arg), WHY??
pb->run((int)5); // call CCC::run(double arg), WHY??
do not differ because their arguments have the type int.
The static type of the pointer pb is BBB *. So the compiler searches the name run in the class BBB.
Within the class only one function with this name is visible. It is the function declared in the class
virtual bool run(double arg)
return false;
So the compiler runs this virtual function with this signature but invokes it using the table of virtual function pointers defined for the class CCC because the dynamic type of the pointer pb is CCC *.
You could make the function declared in the class AAA visible within the class BBB by means of the using declaration. For example
struct BBB : AAA
using AAA:: run;
virtual bool run(double arg)
return false;
;
In this case the declaration of the function (declared in the class AAA) would be also a member declaration inside the class BBB. That is the class BBB will have declarations of two overloaded distinct virtual functions.
Here is a demonstrative program
#include <iostream>
struct AAA
virtual float run(int arg)
return 5.5f;
;
struct BBB : AAA
using AAA:: run;
virtual bool run(double arg)
return false;
;
struct CCC : BBB
virtual float run(int arg)
return 7.7f;
virtual bool run(double arg)
return true;
;
int main()
CCC c;
BBB* pb = &c;
std::cout << pb->run(5) << 'n';
std::cout << pb->run(5.6 ) << 'n';
return 0;
Its output is
7.7
1
To make the situation with the member declarations in a derived class and in its base class consider a similar situation with block scopes.
Here is a demonstrative program
#include <iostream>
void f( int ) std::cout << "void f( int )n";
void f( double ) std::cout << "void f( double )n";
int main()
void f( double );
f( 5 );
f( 5.5 );
return 0;
The inner declaration of the function f in the block scope of the function main hides the other declaration of the function in the global scope.
The program output is
void f( double )
void f( double )
All is simple.
The class BBB has in fact two virtual functions. One is declared in its base class AAA
struct AAA
virtual float run(int arg)
return 5.5f;
;
And other is declared in the class BBB itself.
struct BBB : AAA
virtual bool run(double arg)
return false;
;
The function declared in the class BBB hides the function declared in the class AAA. (Any name declared in a derived class hides an entity with the same name declared in the base class of the derived class)
In the class CCC the both functions are overriden.
These function calls
pb->run(5); // call CCC::run(double arg), WHY??
pb->run((int)5); // call CCC::run(double arg), WHY??
do not differ because their arguments have the type int.
The static type of the pointer pb is BBB *. So the compiler searches the name run in the class BBB.
Within the class only one function with this name is visible. It is the function declared in the class
virtual bool run(double arg)
return false;
So the compiler runs this virtual function with this signature but invokes it using the table of virtual function pointers defined for the class CCC because the dynamic type of the pointer pb is CCC *.
You could make the function declared in the class AAA visible within the class BBB by means of the using declaration. For example
struct BBB : AAA
using AAA:: run;
virtual bool run(double arg)
return false;
;
In this case the declaration of the function (declared in the class AAA) would be also a member declaration inside the class BBB. That is the class BBB will have declarations of two overloaded distinct virtual functions.
Here is a demonstrative program
#include <iostream>
struct AAA
virtual float run(int arg)
return 5.5f;
;
struct BBB : AAA
using AAA:: run;
virtual bool run(double arg)
return false;
;
struct CCC : BBB
virtual float run(int arg)
return 7.7f;
virtual bool run(double arg)
return true;
;
int main()
CCC c;
BBB* pb = &c;
std::cout << pb->run(5) << 'n';
std::cout << pb->run(5.6 ) << 'n';
return 0;
Its output is
7.7
1
To make the situation with the member declarations in a derived class and in its base class consider a similar situation with block scopes.
Here is a demonstrative program
#include <iostream>
void f( int ) std::cout << "void f( int )n";
void f( double ) std::cout << "void f( double )n";
int main()
void f( double );
f( 5 );
f( 5.5 );
return 0;
The inner declaration of the function f in the block scope of the function main hides the other declaration of the function in the global scope.
The program output is
void f( double )
void f( double )
edited 7 hours ago
answered 8 hours ago
Vlad from MoscowVlad from Moscow
150k14 gold badges92 silver badges192 bronze badges
150k14 gold badges92 silver badges192 bronze badges
@LightnessRacesinOrbit Thanks. I updated the post.
– Vlad from Moscow
7 hours ago
>>So the compiler searches the name run in the class BBB. Does it mean than compiler searches only by name but not with full prototype?
– dimasafo
7 hours ago
2
@dimasafo It searches the name. Then it determines that the name belongs to a function and uses the function declaration to call its corresponding definition that is overriden in the class CCC.
– Vlad from Moscow
7 hours ago
add a comment |
@LightnessRacesinOrbit Thanks. I updated the post.
– Vlad from Moscow
7 hours ago
>>So the compiler searches the name run in the class BBB. Does it mean than compiler searches only by name but not with full prototype?
– dimasafo
7 hours ago
2
@dimasafo It searches the name. Then it determines that the name belongs to a function and uses the function declaration to call its corresponding definition that is overriden in the class CCC.
– Vlad from Moscow
7 hours ago
@LightnessRacesinOrbit Thanks. I updated the post.
– Vlad from Moscow
7 hours ago
@LightnessRacesinOrbit Thanks. I updated the post.
– Vlad from Moscow
7 hours ago
>>So the compiler searches the name run in the class BBB. Does it mean than compiler searches only by name but not with full prototype?
– dimasafo
7 hours ago
>>So the compiler searches the name run in the class BBB. Does it mean than compiler searches only by name but not with full prototype?
– dimasafo
7 hours ago
2
2
@dimasafo It searches the name. Then it determines that the name belongs to a function and uses the function declaration to call its corresponding definition that is overriden in the class CCC.
– Vlad from Moscow
7 hours ago
@dimasafo It searches the name. Then it determines that the name belongs to a function and uses the function declaration to call its corresponding definition that is overriden in the class CCC.
– Vlad from Moscow
7 hours ago
add a comment |
When you do
struct BBB : AAA
virtual bool run(double arg)
return false;
;
run has a different signature from run in AAA. This means that BBB::run(double) will hide AAA::run(int). Since it does, the only run that you can call from BBB is bool run(double arg). When you do
pb->run(5);
it finds bool BBB::run(double arg) as that is the only function you can call statically from a BBB and then virtual dispatch kicks in calling CCC::run(double)
In order to get the int version of the function to be called, you need to bring the int version into BBB. You can do this by writing one, or you could use using AAA::run; to import it in. Doing either of those will make pb->run(5); call the int version of run from CCC.
Don't forget, when playing with polymorphism you should declare the top level destructor (AAA's in this case) to be virtual. This allows you to delete objects correctly when using dynamic allocation. For full details see: When to use virtual destructors?
>>This means that BBB::run(double) will hide AAA::run(int) I thought it will hide medhod only for BBB but not for CCC. In fact it is unclear for me. So the vtable will contain only one function. Right?
– dimasafo
8 hours ago
@JeJo: Through anAAA*, you would findfloat run(int)(and only that one, no possibility to callbool run(double))
– Ben Voigt
8 hours ago
@dimasafo Can't say about that. The reason theintversion isn't called is becauseBBBcan only callBBB::run(double), so that is the fucntion that virtual dispatch happens on. Theintversion is never considered.
– NathanOliver
8 hours ago
@dimasafopbis aBBB, so onlyBBB's functions are considered. If you changepbto be aAAA*then theintversion is called.
– NathanOliver
8 hours ago
1
Feels like usingoverridehere would have helped out a lot.
– François Andrieux
7 hours ago
|
show 1 more comment
When you do
struct BBB : AAA
virtual bool run(double arg)
return false;
;
run has a different signature from run in AAA. This means that BBB::run(double) will hide AAA::run(int). Since it does, the only run that you can call from BBB is bool run(double arg). When you do
pb->run(5);
it finds bool BBB::run(double arg) as that is the only function you can call statically from a BBB and then virtual dispatch kicks in calling CCC::run(double)
In order to get the int version of the function to be called, you need to bring the int version into BBB. You can do this by writing one, or you could use using AAA::run; to import it in. Doing either of those will make pb->run(5); call the int version of run from CCC.
Don't forget, when playing with polymorphism you should declare the top level destructor (AAA's in this case) to be virtual. This allows you to delete objects correctly when using dynamic allocation. For full details see: When to use virtual destructors?
>>This means that BBB::run(double) will hide AAA::run(int) I thought it will hide medhod only for BBB but not for CCC. In fact it is unclear for me. So the vtable will contain only one function. Right?
– dimasafo
8 hours ago
@JeJo: Through anAAA*, you would findfloat run(int)(and only that one, no possibility to callbool run(double))
– Ben Voigt
8 hours ago
@dimasafo Can't say about that. The reason theintversion isn't called is becauseBBBcan only callBBB::run(double), so that is the fucntion that virtual dispatch happens on. Theintversion is never considered.
– NathanOliver
8 hours ago
@dimasafopbis aBBB, so onlyBBB's functions are considered. If you changepbto be aAAA*then theintversion is called.
– NathanOliver
8 hours ago
1
Feels like usingoverridehere would have helped out a lot.
– François Andrieux
7 hours ago
|
show 1 more comment
When you do
struct BBB : AAA
virtual bool run(double arg)
return false;
;
run has a different signature from run in AAA. This means that BBB::run(double) will hide AAA::run(int). Since it does, the only run that you can call from BBB is bool run(double arg). When you do
pb->run(5);
it finds bool BBB::run(double arg) as that is the only function you can call statically from a BBB and then virtual dispatch kicks in calling CCC::run(double)
In order to get the int version of the function to be called, you need to bring the int version into BBB. You can do this by writing one, or you could use using AAA::run; to import it in. Doing either of those will make pb->run(5); call the int version of run from CCC.
Don't forget, when playing with polymorphism you should declare the top level destructor (AAA's in this case) to be virtual. This allows you to delete objects correctly when using dynamic allocation. For full details see: When to use virtual destructors?
When you do
struct BBB : AAA
virtual bool run(double arg)
return false;
;
run has a different signature from run in AAA. This means that BBB::run(double) will hide AAA::run(int). Since it does, the only run that you can call from BBB is bool run(double arg). When you do
pb->run(5);
it finds bool BBB::run(double arg) as that is the only function you can call statically from a BBB and then virtual dispatch kicks in calling CCC::run(double)
In order to get the int version of the function to be called, you need to bring the int version into BBB. You can do this by writing one, or you could use using AAA::run; to import it in. Doing either of those will make pb->run(5); call the int version of run from CCC.
Don't forget, when playing with polymorphism you should declare the top level destructor (AAA's in this case) to be virtual. This allows you to delete objects correctly when using dynamic allocation. For full details see: When to use virtual destructors?
edited 7 hours ago
answered 8 hours ago
NathanOliverNathanOliver
113k19 gold badges178 silver badges257 bronze badges
113k19 gold badges178 silver badges257 bronze badges
>>This means that BBB::run(double) will hide AAA::run(int) I thought it will hide medhod only for BBB but not for CCC. In fact it is unclear for me. So the vtable will contain only one function. Right?
– dimasafo
8 hours ago
@JeJo: Through anAAA*, you would findfloat run(int)(and only that one, no possibility to callbool run(double))
– Ben Voigt
8 hours ago
@dimasafo Can't say about that. The reason theintversion isn't called is becauseBBBcan only callBBB::run(double), so that is the fucntion that virtual dispatch happens on. Theintversion is never considered.
– NathanOliver
8 hours ago
@dimasafopbis aBBB, so onlyBBB's functions are considered. If you changepbto be aAAA*then theintversion is called.
– NathanOliver
8 hours ago
1
Feels like usingoverridehere would have helped out a lot.
– François Andrieux
7 hours ago
|
show 1 more comment
>>This means that BBB::run(double) will hide AAA::run(int) I thought it will hide medhod only for BBB but not for CCC. In fact it is unclear for me. So the vtable will contain only one function. Right?
– dimasafo
8 hours ago
@JeJo: Through anAAA*, you would findfloat run(int)(and only that one, no possibility to callbool run(double))
– Ben Voigt
8 hours ago
@dimasafo Can't say about that. The reason theintversion isn't called is becauseBBBcan only callBBB::run(double), so that is the fucntion that virtual dispatch happens on. Theintversion is never considered.
– NathanOliver
8 hours ago
@dimasafopbis aBBB, so onlyBBB's functions are considered. If you changepbto be aAAA*then theintversion is called.
– NathanOliver
8 hours ago
1
Feels like usingoverridehere would have helped out a lot.
– François Andrieux
7 hours ago
>>This means that BBB::run(double) will hide AAA::run(int) I thought it will hide medhod only for BBB but not for CCC. In fact it is unclear for me. So the vtable will contain only one function. Right?
– dimasafo
8 hours ago
>>This means that BBB::run(double) will hide AAA::run(int) I thought it will hide medhod only for BBB but not for CCC. In fact it is unclear for me. So the vtable will contain only one function. Right?
– dimasafo
8 hours ago
@JeJo: Through an
AAA*, you would find float run(int) (and only that one, no possibility to call bool run(double))– Ben Voigt
8 hours ago
@JeJo: Through an
AAA*, you would find float run(int) (and only that one, no possibility to call bool run(double))– Ben Voigt
8 hours ago
@dimasafo Can't say about that. The reason the
int version isn't called is because BBB can only call BBB::run(double), so that is the fucntion that virtual dispatch happens on. The int version is never considered.– NathanOliver
8 hours ago
@dimasafo Can't say about that. The reason the
int version isn't called is because BBB can only call BBB::run(double), so that is the fucntion that virtual dispatch happens on. The int version is never considered.– NathanOliver
8 hours ago
@dimasafo
pb is a BBB, so only BBB's functions are considered. If you change pb to be a AAA* then the int version is called.– NathanOliver
8 hours ago
@dimasafo
pb is a BBB, so only BBB's functions are considered. If you change pb to be a AAA* then the int version is called.– NathanOliver
8 hours ago
1
1
Feels like using
override here would have helped out a lot.– François Andrieux
7 hours ago
Feels like using
override here would have helped out a lot.– François Andrieux
7 hours ago
|
show 1 more comment
dimasafo is a new contributor. Be nice, and check out our Code of Conduct.
dimasafo is a new contributor. Be nice, and check out our Code of Conduct.
dimasafo is a new contributor. Be nice, and check out our Code of Conduct.
dimasafo is a new contributor. Be nice, and check out our Code of Conduct.
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%2f57577757%2fthe-logic-of-invoking-virtual-functions-is-not-clear-or-it-is-method-hiding%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
1
You have misconceptions about function signatures and how these are matching, that's all. Voted to close.
– πάντα ῥεῖ
8 hours ago
8
@πάνταῥεῖ Close for what reason?
– melpomene
8 hours ago
This is not a question about signatures having to match for the virtual method in the derived class. It's phrased confusingly, but that's not what's asked here.
– Sam Varshavchik
8 hours ago
I'm sure we have a few name hiding dupes though
– Lightness Races in Orbit
7 hours ago
I understand! The call works because int can be implicitly converted to double. (otherwise it would cause compilation error) If we replace AAA::run(int) and CCC::run(int) to respectively AAA::run(CustomType) and CCC::run(CustomType) - it would cause compilation error
– dimasafo
7 hours ago