Difference between using non-virtual base class functions versus derived class non-implemented virtual...
up vote
2
down vote
favorite
This question is slightly related to What are the differences between overriding virtual functions and hiding non-virtual functions?, but I'm not asking about the technical details, rather about the usage of non-virtual and virtual functions.
Here's a little background. Let's say I have a base class A and two derived classes B and C
#include <iostream>
class A {
public:
A() {};
virtual void foo() { std::cout << "foo() called in An"; };
virtual void bar() { std::cout << "bar() called from An"; };
void xorp() { std::cout << "xorp() called from An"; };
virtual ~A() {};
};
class B : public A {
public:
B() {};
virtual ~B() {};
virtual void foo() override { std::cout << "foo() called in Bn"; };
//virtual void bar() override not implemented in B, using A::bar();
};
class C : public A {
public:
C() {};
virtual ~C() {};
virtual void foo() override { std::cout << "foo() called in Cn"; };
//virtual bar() override not implemented in C, using A::bar();
};
int main() {
A a{};
B b{};
C c{};
a.foo(); //calls A::foo()
a.bar(); //calls A::bar()
a.xorp(); //calls non-virtual A::xorp()
b.foo(); //calls virtual overridden function B::foo()
b.bar(); //calls virtual non-overridden function A::bar()
b.xorp(); //calls non-virtual A::xorp()
c.foo(); //calls virtual overridden function C::foo()
c.bar(); //calls virtual non-overridden function A::bar()
c.xorp(); //calls non-virtual A::xorp()
return 0;
}
This outputs, as expected, the following:
foo() called in A
bar() called from A
xorp() called from A
foo() called in B
bar() called from A
xorp() called from A
foo() called in C
bar() called from A
xorp() called from A
If I leave the virtual function bar() unimplemented in the derived classes, any call to bar() in the derived classes B and C gets resolved to A::bar(). xorp(), which is a non-virtual function, can also be called from the derived classes as either b.xorp() or b.A::xorp().
If I were to implement a xorp() in B, for example, it would effectively hide the A::xorp() and a call to b.xorp() would actually be a call to b.B::xorp().
Which brings me to my question, using the example above. Let's say I have a helper function that the derived classes need for their implementation.
Is there a difference between having the helper function be a non-virtual member function (like xorp()), versus the helper function being a virtual function that the derived classes do not override (bar())?
Reading through this presentation on class object layout and VTABLEs (https://www.cs.bgu.ac.il/~asharf/SPL/Inheritance.pptx, slides 28-35) I could not really spot a difference, since both non-virtual and non-overridden virtual functions point to the same place (i.e the function in the base class)
Could anyone give me an example where these two approaches would produce different results, or if there is a caveat that I have not spotted?
c++ override virtual-functions name-hiding
add a comment |
up vote
2
down vote
favorite
This question is slightly related to What are the differences between overriding virtual functions and hiding non-virtual functions?, but I'm not asking about the technical details, rather about the usage of non-virtual and virtual functions.
Here's a little background. Let's say I have a base class A and two derived classes B and C
#include <iostream>
class A {
public:
A() {};
virtual void foo() { std::cout << "foo() called in An"; };
virtual void bar() { std::cout << "bar() called from An"; };
void xorp() { std::cout << "xorp() called from An"; };
virtual ~A() {};
};
class B : public A {
public:
B() {};
virtual ~B() {};
virtual void foo() override { std::cout << "foo() called in Bn"; };
//virtual void bar() override not implemented in B, using A::bar();
};
class C : public A {
public:
C() {};
virtual ~C() {};
virtual void foo() override { std::cout << "foo() called in Cn"; };
//virtual bar() override not implemented in C, using A::bar();
};
int main() {
A a{};
B b{};
C c{};
a.foo(); //calls A::foo()
a.bar(); //calls A::bar()
a.xorp(); //calls non-virtual A::xorp()
b.foo(); //calls virtual overridden function B::foo()
b.bar(); //calls virtual non-overridden function A::bar()
b.xorp(); //calls non-virtual A::xorp()
c.foo(); //calls virtual overridden function C::foo()
c.bar(); //calls virtual non-overridden function A::bar()
c.xorp(); //calls non-virtual A::xorp()
return 0;
}
This outputs, as expected, the following:
foo() called in A
bar() called from A
xorp() called from A
foo() called in B
bar() called from A
xorp() called from A
foo() called in C
bar() called from A
xorp() called from A
If I leave the virtual function bar() unimplemented in the derived classes, any call to bar() in the derived classes B and C gets resolved to A::bar(). xorp(), which is a non-virtual function, can also be called from the derived classes as either b.xorp() or b.A::xorp().
If I were to implement a xorp() in B, for example, it would effectively hide the A::xorp() and a call to b.xorp() would actually be a call to b.B::xorp().
Which brings me to my question, using the example above. Let's say I have a helper function that the derived classes need for their implementation.
Is there a difference between having the helper function be a non-virtual member function (like xorp()), versus the helper function being a virtual function that the derived classes do not override (bar())?
Reading through this presentation on class object layout and VTABLEs (https://www.cs.bgu.ac.il/~asharf/SPL/Inheritance.pptx, slides 28-35) I could not really spot a difference, since both non-virtual and non-overridden virtual functions point to the same place (i.e the function in the base class)
Could anyone give me an example where these two approaches would produce different results, or if there is a caveat that I have not spotted?
c++ override virtual-functions name-hiding
No difference. But a derived class might override the function. The usual caveat is that you don't know when it happens, who did it and why he chose to do so. And can break your class doing it. These are high risk factors that you have to think through when you design. Hard to do correctly. Luckily there is a very simple solution, declare the classfinal
. That might produce a phone call some time in the future, but it is one that eliminates all those risks.
– Hans Passant
Nov 11 at 12:54
You don't use virtual inheritance here.
– curiousguy
Nov 13 at 5:02
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
This question is slightly related to What are the differences between overriding virtual functions and hiding non-virtual functions?, but I'm not asking about the technical details, rather about the usage of non-virtual and virtual functions.
Here's a little background. Let's say I have a base class A and two derived classes B and C
#include <iostream>
class A {
public:
A() {};
virtual void foo() { std::cout << "foo() called in An"; };
virtual void bar() { std::cout << "bar() called from An"; };
void xorp() { std::cout << "xorp() called from An"; };
virtual ~A() {};
};
class B : public A {
public:
B() {};
virtual ~B() {};
virtual void foo() override { std::cout << "foo() called in Bn"; };
//virtual void bar() override not implemented in B, using A::bar();
};
class C : public A {
public:
C() {};
virtual ~C() {};
virtual void foo() override { std::cout << "foo() called in Cn"; };
//virtual bar() override not implemented in C, using A::bar();
};
int main() {
A a{};
B b{};
C c{};
a.foo(); //calls A::foo()
a.bar(); //calls A::bar()
a.xorp(); //calls non-virtual A::xorp()
b.foo(); //calls virtual overridden function B::foo()
b.bar(); //calls virtual non-overridden function A::bar()
b.xorp(); //calls non-virtual A::xorp()
c.foo(); //calls virtual overridden function C::foo()
c.bar(); //calls virtual non-overridden function A::bar()
c.xorp(); //calls non-virtual A::xorp()
return 0;
}
This outputs, as expected, the following:
foo() called in A
bar() called from A
xorp() called from A
foo() called in B
bar() called from A
xorp() called from A
foo() called in C
bar() called from A
xorp() called from A
If I leave the virtual function bar() unimplemented in the derived classes, any call to bar() in the derived classes B and C gets resolved to A::bar(). xorp(), which is a non-virtual function, can also be called from the derived classes as either b.xorp() or b.A::xorp().
If I were to implement a xorp() in B, for example, it would effectively hide the A::xorp() and a call to b.xorp() would actually be a call to b.B::xorp().
Which brings me to my question, using the example above. Let's say I have a helper function that the derived classes need for their implementation.
Is there a difference between having the helper function be a non-virtual member function (like xorp()), versus the helper function being a virtual function that the derived classes do not override (bar())?
Reading through this presentation on class object layout and VTABLEs (https://www.cs.bgu.ac.il/~asharf/SPL/Inheritance.pptx, slides 28-35) I could not really spot a difference, since both non-virtual and non-overridden virtual functions point to the same place (i.e the function in the base class)
Could anyone give me an example where these two approaches would produce different results, or if there is a caveat that I have not spotted?
c++ override virtual-functions name-hiding
This question is slightly related to What are the differences between overriding virtual functions and hiding non-virtual functions?, but I'm not asking about the technical details, rather about the usage of non-virtual and virtual functions.
Here's a little background. Let's say I have a base class A and two derived classes B and C
#include <iostream>
class A {
public:
A() {};
virtual void foo() { std::cout << "foo() called in An"; };
virtual void bar() { std::cout << "bar() called from An"; };
void xorp() { std::cout << "xorp() called from An"; };
virtual ~A() {};
};
class B : public A {
public:
B() {};
virtual ~B() {};
virtual void foo() override { std::cout << "foo() called in Bn"; };
//virtual void bar() override not implemented in B, using A::bar();
};
class C : public A {
public:
C() {};
virtual ~C() {};
virtual void foo() override { std::cout << "foo() called in Cn"; };
//virtual bar() override not implemented in C, using A::bar();
};
int main() {
A a{};
B b{};
C c{};
a.foo(); //calls A::foo()
a.bar(); //calls A::bar()
a.xorp(); //calls non-virtual A::xorp()
b.foo(); //calls virtual overridden function B::foo()
b.bar(); //calls virtual non-overridden function A::bar()
b.xorp(); //calls non-virtual A::xorp()
c.foo(); //calls virtual overridden function C::foo()
c.bar(); //calls virtual non-overridden function A::bar()
c.xorp(); //calls non-virtual A::xorp()
return 0;
}
This outputs, as expected, the following:
foo() called in A
bar() called from A
xorp() called from A
foo() called in B
bar() called from A
xorp() called from A
foo() called in C
bar() called from A
xorp() called from A
If I leave the virtual function bar() unimplemented in the derived classes, any call to bar() in the derived classes B and C gets resolved to A::bar(). xorp(), which is a non-virtual function, can also be called from the derived classes as either b.xorp() or b.A::xorp().
If I were to implement a xorp() in B, for example, it would effectively hide the A::xorp() and a call to b.xorp() would actually be a call to b.B::xorp().
Which brings me to my question, using the example above. Let's say I have a helper function that the derived classes need for their implementation.
Is there a difference between having the helper function be a non-virtual member function (like xorp()), versus the helper function being a virtual function that the derived classes do not override (bar())?
Reading through this presentation on class object layout and VTABLEs (https://www.cs.bgu.ac.il/~asharf/SPL/Inheritance.pptx, slides 28-35) I could not really spot a difference, since both non-virtual and non-overridden virtual functions point to the same place (i.e the function in the base class)
Could anyone give me an example where these two approaches would produce different results, or if there is a caveat that I have not spotted?
c++ override virtual-functions name-hiding
c++ override virtual-functions name-hiding
edited Nov 13 at 9:55
curiousguy
4,50622940
4,50622940
asked Nov 11 at 12:13
NotAProgrammer
132
132
No difference. But a derived class might override the function. The usual caveat is that you don't know when it happens, who did it and why he chose to do so. And can break your class doing it. These are high risk factors that you have to think through when you design. Hard to do correctly. Luckily there is a very simple solution, declare the classfinal
. That might produce a phone call some time in the future, but it is one that eliminates all those risks.
– Hans Passant
Nov 11 at 12:54
You don't use virtual inheritance here.
– curiousguy
Nov 13 at 5:02
add a comment |
No difference. But a derived class might override the function. The usual caveat is that you don't know when it happens, who did it and why he chose to do so. And can break your class doing it. These are high risk factors that you have to think through when you design. Hard to do correctly. Luckily there is a very simple solution, declare the classfinal
. That might produce a phone call some time in the future, but it is one that eliminates all those risks.
– Hans Passant
Nov 11 at 12:54
You don't use virtual inheritance here.
– curiousguy
Nov 13 at 5:02
No difference. But a derived class might override the function. The usual caveat is that you don't know when it happens, who did it and why he chose to do so. And can break your class doing it. These are high risk factors that you have to think through when you design. Hard to do correctly. Luckily there is a very simple solution, declare the class
final
. That might produce a phone call some time in the future, but it is one that eliminates all those risks.– Hans Passant
Nov 11 at 12:54
No difference. But a derived class might override the function. The usual caveat is that you don't know when it happens, who did it and why he chose to do so. And can break your class doing it. These are high risk factors that you have to think through when you design. Hard to do correctly. Luckily there is a very simple solution, declare the class
final
. That might produce a phone call some time in the future, but it is one that eliminates all those risks.– Hans Passant
Nov 11 at 12:54
You don't use virtual inheritance here.
– curiousguy
Nov 13 at 5:02
You don't use virtual inheritance here.
– curiousguy
Nov 13 at 5:02
add a comment |
2 Answers
2
active
oldest
votes
up vote
3
down vote
accepted
The flaw in your example is that you aren't using polymorphism. You operate on all the objects directly. You won't notice anything related to overriding, because none of the calls need to be resolved dynamically. And if the call is not resolved dynamically, there is absolutely no difference between virtual functions and non-virtual ones. To see the difference, use a helper free function:
void baz(A& a) {
a.foo();
a.bar();
a.xorp();
}
int main() {
// As before
baz(a);
baz(b);
baz(c);
}
Now you should be able to see a noticeable difference in how the calls to foo
, bar
and baz
are resolved. In particular...
If I were to implement a xorp() in B, for example, it would effectively hide the A::xorp() and a call to b.xorp() would actually be a call to b.B::xorp().
... will no longer be true inside baz
.
"The flaw in your example" - I think the example is specifically constructed to ask if the compiler will do anything differently when polymorphism is not used.
– HostileFork
Nov 11 at 12:38
1
@HostileFork - I dunno, the OP asked "Could anyone give me an example where these two approaches would produce different results, or if there is a caveat that I have not spotted?", which to me implies they are not sure about their example too. But if you think another answer applies, by all means, write it up. Answer diversity is SO's strength.
– StoryTeller
Nov 11 at 12:41
1
Thanks, the example with baz() definitely helped me a lot to understand what I was trying to ask better.
– NotAProgrammer
Nov 11 at 13:50
add a comment |
up vote
0
down vote
Is there a difference between having the helper function be a non-virtual member function (like xorp()), versus the helper function being a virtual function that the derived classes do not override (bar())?
If you mark a method virtual but you never override it, it's behavior will be equivalent to if you'd never marked it virtual. The relationship to other methods it calls in the object is not affected.
That isn't to say there aren't still "differences".
It certainly conveys a difference in intent to those reading the code. If your xorp() method is not virtual--but relies on virtual methods to implement its behavior--then people will understand "xorpiness" as having certain fixed properties. They would likely try to avoid a redefinition of xorp() in any derived classes, and know to only affect the xorpiness indirectly through defining the virtual methods it depends on.
Plus, the compiler can't always know if you're going to use a virtual override or not. So it can't optimize out the extra code for virtual dispatch--even if you aren't "taking advantage" of it. (Occasionally it can, like if you have a class you never derive from and don't export it...the virtual may just get dropped.)
And with exported classes you expect other people to use: just because you never overrode a method doesn't mean someone else won't. Unless you use final
and prevent derivation of your objects (which isn't considered terribly friendly to do, unless you've got really good reasons). So if you make something virtual, the ability is there, and once someone else adds an override then yes--there will be a difference at that point.
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
accepted
The flaw in your example is that you aren't using polymorphism. You operate on all the objects directly. You won't notice anything related to overriding, because none of the calls need to be resolved dynamically. And if the call is not resolved dynamically, there is absolutely no difference between virtual functions and non-virtual ones. To see the difference, use a helper free function:
void baz(A& a) {
a.foo();
a.bar();
a.xorp();
}
int main() {
// As before
baz(a);
baz(b);
baz(c);
}
Now you should be able to see a noticeable difference in how the calls to foo
, bar
and baz
are resolved. In particular...
If I were to implement a xorp() in B, for example, it would effectively hide the A::xorp() and a call to b.xorp() would actually be a call to b.B::xorp().
... will no longer be true inside baz
.
"The flaw in your example" - I think the example is specifically constructed to ask if the compiler will do anything differently when polymorphism is not used.
– HostileFork
Nov 11 at 12:38
1
@HostileFork - I dunno, the OP asked "Could anyone give me an example where these two approaches would produce different results, or if there is a caveat that I have not spotted?", which to me implies they are not sure about their example too. But if you think another answer applies, by all means, write it up. Answer diversity is SO's strength.
– StoryTeller
Nov 11 at 12:41
1
Thanks, the example with baz() definitely helped me a lot to understand what I was trying to ask better.
– NotAProgrammer
Nov 11 at 13:50
add a comment |
up vote
3
down vote
accepted
The flaw in your example is that you aren't using polymorphism. You operate on all the objects directly. You won't notice anything related to overriding, because none of the calls need to be resolved dynamically. And if the call is not resolved dynamically, there is absolutely no difference between virtual functions and non-virtual ones. To see the difference, use a helper free function:
void baz(A& a) {
a.foo();
a.bar();
a.xorp();
}
int main() {
// As before
baz(a);
baz(b);
baz(c);
}
Now you should be able to see a noticeable difference in how the calls to foo
, bar
and baz
are resolved. In particular...
If I were to implement a xorp() in B, for example, it would effectively hide the A::xorp() and a call to b.xorp() would actually be a call to b.B::xorp().
... will no longer be true inside baz
.
"The flaw in your example" - I think the example is specifically constructed to ask if the compiler will do anything differently when polymorphism is not used.
– HostileFork
Nov 11 at 12:38
1
@HostileFork - I dunno, the OP asked "Could anyone give me an example where these two approaches would produce different results, or if there is a caveat that I have not spotted?", which to me implies they are not sure about their example too. But if you think another answer applies, by all means, write it up. Answer diversity is SO's strength.
– StoryTeller
Nov 11 at 12:41
1
Thanks, the example with baz() definitely helped me a lot to understand what I was trying to ask better.
– NotAProgrammer
Nov 11 at 13:50
add a comment |
up vote
3
down vote
accepted
up vote
3
down vote
accepted
The flaw in your example is that you aren't using polymorphism. You operate on all the objects directly. You won't notice anything related to overriding, because none of the calls need to be resolved dynamically. And if the call is not resolved dynamically, there is absolutely no difference between virtual functions and non-virtual ones. To see the difference, use a helper free function:
void baz(A& a) {
a.foo();
a.bar();
a.xorp();
}
int main() {
// As before
baz(a);
baz(b);
baz(c);
}
Now you should be able to see a noticeable difference in how the calls to foo
, bar
and baz
are resolved. In particular...
If I were to implement a xorp() in B, for example, it would effectively hide the A::xorp() and a call to b.xorp() would actually be a call to b.B::xorp().
... will no longer be true inside baz
.
The flaw in your example is that you aren't using polymorphism. You operate on all the objects directly. You won't notice anything related to overriding, because none of the calls need to be resolved dynamically. And if the call is not resolved dynamically, there is absolutely no difference between virtual functions and non-virtual ones. To see the difference, use a helper free function:
void baz(A& a) {
a.foo();
a.bar();
a.xorp();
}
int main() {
// As before
baz(a);
baz(b);
baz(c);
}
Now you should be able to see a noticeable difference in how the calls to foo
, bar
and baz
are resolved. In particular...
If I were to implement a xorp() in B, for example, it would effectively hide the A::xorp() and a call to b.xorp() would actually be a call to b.B::xorp().
... will no longer be true inside baz
.
edited Nov 11 at 12:50
answered Nov 11 at 12:36
StoryTeller
90.9k12181247
90.9k12181247
"The flaw in your example" - I think the example is specifically constructed to ask if the compiler will do anything differently when polymorphism is not used.
– HostileFork
Nov 11 at 12:38
1
@HostileFork - I dunno, the OP asked "Could anyone give me an example where these two approaches would produce different results, or if there is a caveat that I have not spotted?", which to me implies they are not sure about their example too. But if you think another answer applies, by all means, write it up. Answer diversity is SO's strength.
– StoryTeller
Nov 11 at 12:41
1
Thanks, the example with baz() definitely helped me a lot to understand what I was trying to ask better.
– NotAProgrammer
Nov 11 at 13:50
add a comment |
"The flaw in your example" - I think the example is specifically constructed to ask if the compiler will do anything differently when polymorphism is not used.
– HostileFork
Nov 11 at 12:38
1
@HostileFork - I dunno, the OP asked "Could anyone give me an example where these two approaches would produce different results, or if there is a caveat that I have not spotted?", which to me implies they are not sure about their example too. But if you think another answer applies, by all means, write it up. Answer diversity is SO's strength.
– StoryTeller
Nov 11 at 12:41
1
Thanks, the example with baz() definitely helped me a lot to understand what I was trying to ask better.
– NotAProgrammer
Nov 11 at 13:50
"The flaw in your example" - I think the example is specifically constructed to ask if the compiler will do anything differently when polymorphism is not used.
– HostileFork
Nov 11 at 12:38
"The flaw in your example" - I think the example is specifically constructed to ask if the compiler will do anything differently when polymorphism is not used.
– HostileFork
Nov 11 at 12:38
1
1
@HostileFork - I dunno, the OP asked "Could anyone give me an example where these two approaches would produce different results, or if there is a caveat that I have not spotted?", which to me implies they are not sure about their example too. But if you think another answer applies, by all means, write it up. Answer diversity is SO's strength.
– StoryTeller
Nov 11 at 12:41
@HostileFork - I dunno, the OP asked "Could anyone give me an example where these two approaches would produce different results, or if there is a caveat that I have not spotted?", which to me implies they are not sure about their example too. But if you think another answer applies, by all means, write it up. Answer diversity is SO's strength.
– StoryTeller
Nov 11 at 12:41
1
1
Thanks, the example with baz() definitely helped me a lot to understand what I was trying to ask better.
– NotAProgrammer
Nov 11 at 13:50
Thanks, the example with baz() definitely helped me a lot to understand what I was trying to ask better.
– NotAProgrammer
Nov 11 at 13:50
add a comment |
up vote
0
down vote
Is there a difference between having the helper function be a non-virtual member function (like xorp()), versus the helper function being a virtual function that the derived classes do not override (bar())?
If you mark a method virtual but you never override it, it's behavior will be equivalent to if you'd never marked it virtual. The relationship to other methods it calls in the object is not affected.
That isn't to say there aren't still "differences".
It certainly conveys a difference in intent to those reading the code. If your xorp() method is not virtual--but relies on virtual methods to implement its behavior--then people will understand "xorpiness" as having certain fixed properties. They would likely try to avoid a redefinition of xorp() in any derived classes, and know to only affect the xorpiness indirectly through defining the virtual methods it depends on.
Plus, the compiler can't always know if you're going to use a virtual override or not. So it can't optimize out the extra code for virtual dispatch--even if you aren't "taking advantage" of it. (Occasionally it can, like if you have a class you never derive from and don't export it...the virtual may just get dropped.)
And with exported classes you expect other people to use: just because you never overrode a method doesn't mean someone else won't. Unless you use final
and prevent derivation of your objects (which isn't considered terribly friendly to do, unless you've got really good reasons). So if you make something virtual, the ability is there, and once someone else adds an override then yes--there will be a difference at that point.
add a comment |
up vote
0
down vote
Is there a difference between having the helper function be a non-virtual member function (like xorp()), versus the helper function being a virtual function that the derived classes do not override (bar())?
If you mark a method virtual but you never override it, it's behavior will be equivalent to if you'd never marked it virtual. The relationship to other methods it calls in the object is not affected.
That isn't to say there aren't still "differences".
It certainly conveys a difference in intent to those reading the code. If your xorp() method is not virtual--but relies on virtual methods to implement its behavior--then people will understand "xorpiness" as having certain fixed properties. They would likely try to avoid a redefinition of xorp() in any derived classes, and know to only affect the xorpiness indirectly through defining the virtual methods it depends on.
Plus, the compiler can't always know if you're going to use a virtual override or not. So it can't optimize out the extra code for virtual dispatch--even if you aren't "taking advantage" of it. (Occasionally it can, like if you have a class you never derive from and don't export it...the virtual may just get dropped.)
And with exported classes you expect other people to use: just because you never overrode a method doesn't mean someone else won't. Unless you use final
and prevent derivation of your objects (which isn't considered terribly friendly to do, unless you've got really good reasons). So if you make something virtual, the ability is there, and once someone else adds an override then yes--there will be a difference at that point.
add a comment |
up vote
0
down vote
up vote
0
down vote
Is there a difference between having the helper function be a non-virtual member function (like xorp()), versus the helper function being a virtual function that the derived classes do not override (bar())?
If you mark a method virtual but you never override it, it's behavior will be equivalent to if you'd never marked it virtual. The relationship to other methods it calls in the object is not affected.
That isn't to say there aren't still "differences".
It certainly conveys a difference in intent to those reading the code. If your xorp() method is not virtual--but relies on virtual methods to implement its behavior--then people will understand "xorpiness" as having certain fixed properties. They would likely try to avoid a redefinition of xorp() in any derived classes, and know to only affect the xorpiness indirectly through defining the virtual methods it depends on.
Plus, the compiler can't always know if you're going to use a virtual override or not. So it can't optimize out the extra code for virtual dispatch--even if you aren't "taking advantage" of it. (Occasionally it can, like if you have a class you never derive from and don't export it...the virtual may just get dropped.)
And with exported classes you expect other people to use: just because you never overrode a method doesn't mean someone else won't. Unless you use final
and prevent derivation of your objects (which isn't considered terribly friendly to do, unless you've got really good reasons). So if you make something virtual, the ability is there, and once someone else adds an override then yes--there will be a difference at that point.
Is there a difference between having the helper function be a non-virtual member function (like xorp()), versus the helper function being a virtual function that the derived classes do not override (bar())?
If you mark a method virtual but you never override it, it's behavior will be equivalent to if you'd never marked it virtual. The relationship to other methods it calls in the object is not affected.
That isn't to say there aren't still "differences".
It certainly conveys a difference in intent to those reading the code. If your xorp() method is not virtual--but relies on virtual methods to implement its behavior--then people will understand "xorpiness" as having certain fixed properties. They would likely try to avoid a redefinition of xorp() in any derived classes, and know to only affect the xorpiness indirectly through defining the virtual methods it depends on.
Plus, the compiler can't always know if you're going to use a virtual override or not. So it can't optimize out the extra code for virtual dispatch--even if you aren't "taking advantage" of it. (Occasionally it can, like if you have a class you never derive from and don't export it...the virtual may just get dropped.)
And with exported classes you expect other people to use: just because you never overrode a method doesn't mean someone else won't. Unless you use final
and prevent derivation of your objects (which isn't considered terribly friendly to do, unless you've got really good reasons). So if you make something virtual, the ability is there, and once someone else adds an override then yes--there will be a difference at that point.
edited Nov 11 at 13:09
answered Nov 11 at 12:58
HostileFork
24.7k775131
24.7k775131
add a comment |
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.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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%2f53248642%2fdifference-between-using-non-virtual-base-class-functions-versus-derived-class-n%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
No difference. But a derived class might override the function. The usual caveat is that you don't know when it happens, who did it and why he chose to do so. And can break your class doing it. These are high risk factors that you have to think through when you design. Hard to do correctly. Luckily there is a very simple solution, declare the class
final
. That might produce a phone call some time in the future, but it is one that eliminates all those risks.– Hans Passant
Nov 11 at 12:54
You don't use virtual inheritance here.
– curiousguy
Nov 13 at 5:02