Default value parameter in pure virtual function
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
|
show 2 more comments
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
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
|
show 2 more comments
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
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
c++ inheritance polymorphism
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
|
show 2 more comments
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
|
show 2 more comments
1 Answer
1
active
oldest
votes
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.
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
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%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
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.
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
add a comment |
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.
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
add a comment |
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.
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.
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
add a comment |
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
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53272510%2fdefault-value-parameter-in-pure-virtual-function%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
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