Default value parameter in pure virtual function












2















I submitted some code as:



Abstract class:



virtual void someFunction(std::vector<someObject*> & iObject) = 0;
virtual void someFunction(std::vector<someObject*> & iObject, bool aSwitch) = 0;


The first function was existing, I added the second to avoid having a default value parameter in a pure method.



Header in the derived class:



virtual void someFunction(std::vector<someObject*> & iObject);
virtual void someFunction(std::vector<someObject*> & iObject, bool aSwitch = false);


Usage as expected:



someFunction(std::vector<someObject*> & Object);


or



someFunction(std::vector<someObject*> & Object, true);


someFunction as it was - already existed, I added the switch.
It works well but I'm confused.



I have a code reviewer saying I should include a default value in the pure virtual function to avoid the two function signatures. I remember reading that default values in pure virtuals are not a good idea but I can't argue a valid point and the articles dont seem clear as to why.



Would it cause ambiguity if I added the default value and if so would I still need the default value in the derived virtual method?



Could I just add the default value in the pure virtual function and do away with the first function in the derived class header? What is the best practice here?










share|improve this question

























  • Just rename as someFunction1 and someFunction2 to make life easier.

    – seccpur
    Nov 13 '18 at 1:42











  • Legacy code - cant do that.

    – solarflare
    Nov 13 '18 at 1:42











  • At least the reader would be confused as they would be unsure which one was intended to call. It could be relying on the compiler. So follow your code reviewer's comment.

    – Charlie
    Nov 13 '18 at 1:44











  • Best practice is to not mix default values with virtual methods, because it has confusing semantics.

    – spectras
    Nov 13 '18 at 2:00






  • 1





    Related question about default parameters and virtual functions

    – 1201ProgramAlarm
    Nov 13 '18 at 2:34
















2















I submitted some code as:



Abstract class:



virtual void someFunction(std::vector<someObject*> & iObject) = 0;
virtual void someFunction(std::vector<someObject*> & iObject, bool aSwitch) = 0;


The first function was existing, I added the second to avoid having a default value parameter in a pure method.



Header in the derived class:



virtual void someFunction(std::vector<someObject*> & iObject);
virtual void someFunction(std::vector<someObject*> & iObject, bool aSwitch = false);


Usage as expected:



someFunction(std::vector<someObject*> & Object);


or



someFunction(std::vector<someObject*> & Object, true);


someFunction as it was - already existed, I added the switch.
It works well but I'm confused.



I have a code reviewer saying I should include a default value in the pure virtual function to avoid the two function signatures. I remember reading that default values in pure virtuals are not a good idea but I can't argue a valid point and the articles dont seem clear as to why.



Would it cause ambiguity if I added the default value and if so would I still need the default value in the derived virtual method?



Could I just add the default value in the pure virtual function and do away with the first function in the derived class header? What is the best practice here?










share|improve this question

























  • Just rename as someFunction1 and someFunction2 to make life easier.

    – seccpur
    Nov 13 '18 at 1:42











  • Legacy code - cant do that.

    – solarflare
    Nov 13 '18 at 1:42











  • At least the reader would be confused as they would be unsure which one was intended to call. It could be relying on the compiler. So follow your code reviewer's comment.

    – Charlie
    Nov 13 '18 at 1:44











  • Best practice is to not mix default values with virtual methods, because it has confusing semantics.

    – spectras
    Nov 13 '18 at 2:00






  • 1





    Related question about default parameters and virtual functions

    – 1201ProgramAlarm
    Nov 13 '18 at 2:34














2












2








2








I submitted some code as:



Abstract class:



virtual void someFunction(std::vector<someObject*> & iObject) = 0;
virtual void someFunction(std::vector<someObject*> & iObject, bool aSwitch) = 0;


The first function was existing, I added the second to avoid having a default value parameter in a pure method.



Header in the derived class:



virtual void someFunction(std::vector<someObject*> & iObject);
virtual void someFunction(std::vector<someObject*> & iObject, bool aSwitch = false);


Usage as expected:



someFunction(std::vector<someObject*> & Object);


or



someFunction(std::vector<someObject*> & Object, true);


someFunction as it was - already existed, I added the switch.
It works well but I'm confused.



I have a code reviewer saying I should include a default value in the pure virtual function to avoid the two function signatures. I remember reading that default values in pure virtuals are not a good idea but I can't argue a valid point and the articles dont seem clear as to why.



Would it cause ambiguity if I added the default value and if so would I still need the default value in the derived virtual method?



Could I just add the default value in the pure virtual function and do away with the first function in the derived class header? What is the best practice here?










share|improve this question
















I submitted some code as:



Abstract class:



virtual void someFunction(std::vector<someObject*> & iObject) = 0;
virtual void someFunction(std::vector<someObject*> & iObject, bool aSwitch) = 0;


The first function was existing, I added the second to avoid having a default value parameter in a pure method.



Header in the derived class:



virtual void someFunction(std::vector<someObject*> & iObject);
virtual void someFunction(std::vector<someObject*> & iObject, bool aSwitch = false);


Usage as expected:



someFunction(std::vector<someObject*> & Object);


or



someFunction(std::vector<someObject*> & Object, true);


someFunction as it was - already existed, I added the switch.
It works well but I'm confused.



I have a code reviewer saying I should include a default value in the pure virtual function to avoid the two function signatures. I remember reading that default values in pure virtuals are not a good idea but I can't argue a valid point and the articles dont seem clear as to why.



Would it cause ambiguity if I added the default value and if so would I still need the default value in the derived virtual method?



Could I just add the default value in the pure virtual function and do away with the first function in the derived class header? What is the best practice here?







c++ inheritance polymorphism






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 13 '18 at 1:50







solarflare

















asked Nov 13 '18 at 1:35









solarflaresolarflare

36219




36219













  • Just rename as someFunction1 and someFunction2 to make life easier.

    – seccpur
    Nov 13 '18 at 1:42











  • Legacy code - cant do that.

    – solarflare
    Nov 13 '18 at 1:42











  • At least the reader would be confused as they would be unsure which one was intended to call. It could be relying on the compiler. So follow your code reviewer's comment.

    – Charlie
    Nov 13 '18 at 1:44











  • Best practice is to not mix default values with virtual methods, because it has confusing semantics.

    – spectras
    Nov 13 '18 at 2:00






  • 1





    Related question about default parameters and virtual functions

    – 1201ProgramAlarm
    Nov 13 '18 at 2:34



















  • Just rename as someFunction1 and someFunction2 to make life easier.

    – seccpur
    Nov 13 '18 at 1:42











  • Legacy code - cant do that.

    – solarflare
    Nov 13 '18 at 1:42











  • At least the reader would be confused as they would be unsure which one was intended to call. It could be relying on the compiler. So follow your code reviewer's comment.

    – Charlie
    Nov 13 '18 at 1:44











  • Best practice is to not mix default values with virtual methods, because it has confusing semantics.

    – spectras
    Nov 13 '18 at 2:00






  • 1





    Related question about default parameters and virtual functions

    – 1201ProgramAlarm
    Nov 13 '18 at 2:34

















Just rename as someFunction1 and someFunction2 to make life easier.

– seccpur
Nov 13 '18 at 1:42





Just rename as someFunction1 and someFunction2 to make life easier.

– seccpur
Nov 13 '18 at 1:42













Legacy code - cant do that.

– solarflare
Nov 13 '18 at 1:42





Legacy code - cant do that.

– solarflare
Nov 13 '18 at 1:42













At least the reader would be confused as they would be unsure which one was intended to call. It could be relying on the compiler. So follow your code reviewer's comment.

– Charlie
Nov 13 '18 at 1:44





At least the reader would be confused as they would be unsure which one was intended to call. It could be relying on the compiler. So follow your code reviewer's comment.

– Charlie
Nov 13 '18 at 1:44













Best practice is to not mix default values with virtual methods, because it has confusing semantics.

– spectras
Nov 13 '18 at 2:00





Best practice is to not mix default values with virtual methods, because it has confusing semantics.

– spectras
Nov 13 '18 at 2:00




1




1





Related question about default parameters and virtual functions

– 1201ProgramAlarm
Nov 13 '18 at 2:34





Related question about default parameters and virtual functions

– 1201ProgramAlarm
Nov 13 '18 at 2:34












1 Answer
1






active

oldest

votes


















2














Default arguments in general



The default arguments for functions are not bound to the function itself, but to the calling context: defaults declared for for the function in the scope in which it is called will be used (See C++ standard, [dcl.fct.default]). For example:



void f(int a=1);     // forward declaration with a default value for the compilation unit
void f(int a) // definition
{
cout<<a<<endl;
}
void g() {
void f(int a=2); // declaration in the scope of g
f();
}
int main() {
f(); // uses general default => 1
g(); // uses default defined in g => 2
return 0;
}


Default arguments for virtual functions



This logic applies to all functions, so also the pure virtual functions. The only thing, is that the function declaration (and its defaults) that is considered is the one of the object class known by the compiler. So the same function of the same object may have different default arguments, depending on the object type used to invoke it. For example:



struct A {
virtual void f(int a=1) = 0;
};
struct B:A {
void f(int a) override ;
};
struct C:A {
void f(int a=2) override ;
};

void B::f(int a) // definition
{
cout<<"B"<<a<<endl;
}
void C::f(int a) // definition
{
cout<<"C"<<a<<endl;
}

int main() {
B b;
C c;
A *x=&c, *y=&b; // points to the same objects but using a polymorphic pointer
x->f(); // default value defined for A::f() but with the implementation of C ==> C1
y->f(); // default value defined for A::f() but with the implementation of B ==> B1
// b.f(); // default not defined for B::f() so cannot compile
c.f(); // default value defined for C::f(); ==> C2
}


Good to know




  • Default arguments don't alter the signature of the function. It's still the same function.

  • Different default arguments don't affect the ODR rule. So you could use different default values in different compilation units, and it would still be the same function.

  • The default arguments are provided by the caller, not by the function itself

  • If different default arguments are defined for base and derived classes, you need to be extremely careful, since different defaults might be used depending on how you call the function.






share|improve this answer


























  • This is pretty confusing tbh

    – solarflare
    Nov 18 '18 at 23:28






  • 1





    @solarflare yes. Whenever several defaults are used, there is a risk of confusion. In practice, most often a single default is defined in the header. This way, the use of the default is very predictable (and easier to maintain). For virtual functions it is tricky. As you see, defining the default for the pure virtual is not sufficient. But in practice, you may define the default in the header of the abstract class, and define the same default for all the overrides of the function.

    – Christophe
    Nov 18 '18 at 23:38











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%2f53272510%2fdefault-value-parameter-in-pure-virtual-function%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














Default arguments in general



The default arguments for functions are not bound to the function itself, but to the calling context: defaults declared for for the function in the scope in which it is called will be used (See C++ standard, [dcl.fct.default]). For example:



void f(int a=1);     // forward declaration with a default value for the compilation unit
void f(int a) // definition
{
cout<<a<<endl;
}
void g() {
void f(int a=2); // declaration in the scope of g
f();
}
int main() {
f(); // uses general default => 1
g(); // uses default defined in g => 2
return 0;
}


Default arguments for virtual functions



This logic applies to all functions, so also the pure virtual functions. The only thing, is that the function declaration (and its defaults) that is considered is the one of the object class known by the compiler. So the same function of the same object may have different default arguments, depending on the object type used to invoke it. For example:



struct A {
virtual void f(int a=1) = 0;
};
struct B:A {
void f(int a) override ;
};
struct C:A {
void f(int a=2) override ;
};

void B::f(int a) // definition
{
cout<<"B"<<a<<endl;
}
void C::f(int a) // definition
{
cout<<"C"<<a<<endl;
}

int main() {
B b;
C c;
A *x=&c, *y=&b; // points to the same objects but using a polymorphic pointer
x->f(); // default value defined for A::f() but with the implementation of C ==> C1
y->f(); // default value defined for A::f() but with the implementation of B ==> B1
// b.f(); // default not defined for B::f() so cannot compile
c.f(); // default value defined for C::f(); ==> C2
}


Good to know




  • Default arguments don't alter the signature of the function. It's still the same function.

  • Different default arguments don't affect the ODR rule. So you could use different default values in different compilation units, and it would still be the same function.

  • The default arguments are provided by the caller, not by the function itself

  • If different default arguments are defined for base and derived classes, you need to be extremely careful, since different defaults might be used depending on how you call the function.






share|improve this answer


























  • This is pretty confusing tbh

    – solarflare
    Nov 18 '18 at 23:28






  • 1





    @solarflare yes. Whenever several defaults are used, there is a risk of confusion. In practice, most often a single default is defined in the header. This way, the use of the default is very predictable (and easier to maintain). For virtual functions it is tricky. As you see, defining the default for the pure virtual is not sufficient. But in practice, you may define the default in the header of the abstract class, and define the same default for all the overrides of the function.

    – Christophe
    Nov 18 '18 at 23:38
















2














Default arguments in general



The default arguments for functions are not bound to the function itself, but to the calling context: defaults declared for for the function in the scope in which it is called will be used (See C++ standard, [dcl.fct.default]). For example:



void f(int a=1);     // forward declaration with a default value for the compilation unit
void f(int a) // definition
{
cout<<a<<endl;
}
void g() {
void f(int a=2); // declaration in the scope of g
f();
}
int main() {
f(); // uses general default => 1
g(); // uses default defined in g => 2
return 0;
}


Default arguments for virtual functions



This logic applies to all functions, so also the pure virtual functions. The only thing, is that the function declaration (and its defaults) that is considered is the one of the object class known by the compiler. So the same function of the same object may have different default arguments, depending on the object type used to invoke it. For example:



struct A {
virtual void f(int a=1) = 0;
};
struct B:A {
void f(int a) override ;
};
struct C:A {
void f(int a=2) override ;
};

void B::f(int a) // definition
{
cout<<"B"<<a<<endl;
}
void C::f(int a) // definition
{
cout<<"C"<<a<<endl;
}

int main() {
B b;
C c;
A *x=&c, *y=&b; // points to the same objects but using a polymorphic pointer
x->f(); // default value defined for A::f() but with the implementation of C ==> C1
y->f(); // default value defined for A::f() but with the implementation of B ==> B1
// b.f(); // default not defined for B::f() so cannot compile
c.f(); // default value defined for C::f(); ==> C2
}


Good to know




  • Default arguments don't alter the signature of the function. It's still the same function.

  • Different default arguments don't affect the ODR rule. So you could use different default values in different compilation units, and it would still be the same function.

  • The default arguments are provided by the caller, not by the function itself

  • If different default arguments are defined for base and derived classes, you need to be extremely careful, since different defaults might be used depending on how you call the function.






share|improve this answer


























  • This is pretty confusing tbh

    – solarflare
    Nov 18 '18 at 23:28






  • 1





    @solarflare yes. Whenever several defaults are used, there is a risk of confusion. In practice, most often a single default is defined in the header. This way, the use of the default is very predictable (and easier to maintain). For virtual functions it is tricky. As you see, defining the default for the pure virtual is not sufficient. But in practice, you may define the default in the header of the abstract class, and define the same default for all the overrides of the function.

    – Christophe
    Nov 18 '18 at 23:38














2












2








2







Default arguments in general



The default arguments for functions are not bound to the function itself, but to the calling context: defaults declared for for the function in the scope in which it is called will be used (See C++ standard, [dcl.fct.default]). For example:



void f(int a=1);     // forward declaration with a default value for the compilation unit
void f(int a) // definition
{
cout<<a<<endl;
}
void g() {
void f(int a=2); // declaration in the scope of g
f();
}
int main() {
f(); // uses general default => 1
g(); // uses default defined in g => 2
return 0;
}


Default arguments for virtual functions



This logic applies to all functions, so also the pure virtual functions. The only thing, is that the function declaration (and its defaults) that is considered is the one of the object class known by the compiler. So the same function of the same object may have different default arguments, depending on the object type used to invoke it. For example:



struct A {
virtual void f(int a=1) = 0;
};
struct B:A {
void f(int a) override ;
};
struct C:A {
void f(int a=2) override ;
};

void B::f(int a) // definition
{
cout<<"B"<<a<<endl;
}
void C::f(int a) // definition
{
cout<<"C"<<a<<endl;
}

int main() {
B b;
C c;
A *x=&c, *y=&b; // points to the same objects but using a polymorphic pointer
x->f(); // default value defined for A::f() but with the implementation of C ==> C1
y->f(); // default value defined for A::f() but with the implementation of B ==> B1
// b.f(); // default not defined for B::f() so cannot compile
c.f(); // default value defined for C::f(); ==> C2
}


Good to know




  • Default arguments don't alter the signature of the function. It's still the same function.

  • Different default arguments don't affect the ODR rule. So you could use different default values in different compilation units, and it would still be the same function.

  • The default arguments are provided by the caller, not by the function itself

  • If different default arguments are defined for base and derived classes, you need to be extremely careful, since different defaults might be used depending on how you call the function.






share|improve this answer















Default arguments in general



The default arguments for functions are not bound to the function itself, but to the calling context: defaults declared for for the function in the scope in which it is called will be used (See C++ standard, [dcl.fct.default]). For example:



void f(int a=1);     // forward declaration with a default value for the compilation unit
void f(int a) // definition
{
cout<<a<<endl;
}
void g() {
void f(int a=2); // declaration in the scope of g
f();
}
int main() {
f(); // uses general default => 1
g(); // uses default defined in g => 2
return 0;
}


Default arguments for virtual functions



This logic applies to all functions, so also the pure virtual functions. The only thing, is that the function declaration (and its defaults) that is considered is the one of the object class known by the compiler. So the same function of the same object may have different default arguments, depending on the object type used to invoke it. For example:



struct A {
virtual void f(int a=1) = 0;
};
struct B:A {
void f(int a) override ;
};
struct C:A {
void f(int a=2) override ;
};

void B::f(int a) // definition
{
cout<<"B"<<a<<endl;
}
void C::f(int a) // definition
{
cout<<"C"<<a<<endl;
}

int main() {
B b;
C c;
A *x=&c, *y=&b; // points to the same objects but using a polymorphic pointer
x->f(); // default value defined for A::f() but with the implementation of C ==> C1
y->f(); // default value defined for A::f() but with the implementation of B ==> B1
// b.f(); // default not defined for B::f() so cannot compile
c.f(); // default value defined for C::f(); ==> C2
}


Good to know




  • Default arguments don't alter the signature of the function. It's still the same function.

  • Different default arguments don't affect the ODR rule. So you could use different default values in different compilation units, and it would still be the same function.

  • The default arguments are provided by the caller, not by the function itself

  • If different default arguments are defined for base and derived classes, you need to be extremely careful, since different defaults might be used depending on how you call the function.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 15 '18 at 23:46

























answered Nov 15 '18 at 23:38









ChristopheChristophe

39k43474




39k43474













  • This is pretty confusing tbh

    – solarflare
    Nov 18 '18 at 23:28






  • 1





    @solarflare yes. Whenever several defaults are used, there is a risk of confusion. In practice, most often a single default is defined in the header. This way, the use of the default is very predictable (and easier to maintain). For virtual functions it is tricky. As you see, defining the default for the pure virtual is not sufficient. But in practice, you may define the default in the header of the abstract class, and define the same default for all the overrides of the function.

    – Christophe
    Nov 18 '18 at 23:38



















  • This is pretty confusing tbh

    – solarflare
    Nov 18 '18 at 23:28






  • 1





    @solarflare yes. Whenever several defaults are used, there is a risk of confusion. In practice, most often a single default is defined in the header. This way, the use of the default is very predictable (and easier to maintain). For virtual functions it is tricky. As you see, defining the default for the pure virtual is not sufficient. But in practice, you may define the default in the header of the abstract class, and define the same default for all the overrides of the function.

    – Christophe
    Nov 18 '18 at 23:38

















This is pretty confusing tbh

– solarflare
Nov 18 '18 at 23:28





This is pretty confusing tbh

– solarflare
Nov 18 '18 at 23:28




1




1





@solarflare yes. Whenever several defaults are used, there is a risk of confusion. In practice, most often a single default is defined in the header. This way, the use of the default is very predictable (and easier to maintain). For virtual functions it is tricky. As you see, defining the default for the pure virtual is not sufficient. But in practice, you may define the default in the header of the abstract class, and define the same default for all the overrides of the function.

– Christophe
Nov 18 '18 at 23:38





@solarflare yes. Whenever several defaults are used, there is a risk of confusion. In practice, most often a single default is defined in the header. This way, the use of the default is very predictable (and easier to maintain). For virtual functions it is tricky. As you see, defining the default for the pure virtual is not sufficient. But in practice, you may define the default in the header of the abstract class, and define the same default for all the overrides of the function.

– Christophe
Nov 18 '18 at 23:38


















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%2f53272510%2fdefault-value-parameter-in-pure-virtual-function%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

Florida Star v. B. J. F.

Danny Elfman

Lugert, Oklahoma