-
July 17th, 2013, 06:09 PM
#1
virtual breaks encapsulation in C++?
Here is the code,
Code:
class A
{
public:
virtual void foo(){}
};
class B : public A
{
private:
virtual void foo(){}
};
void main()
{
B b;
A* pA = &b;
pA->foo();
}
Obviously when you call pA->foo, it will call foo defined in B. But foo defined in B is private. It is not supposed to be called outside the class B. So it looks like virtual breaks encapsulation.
-
July 17th, 2013, 09:07 PM
#2
Re: virtual breaks encapsulation in C++?
Originally Posted by LarryChen
Obviously when you call pA->foo, it will call foo defined in B.
pA is not a pointer to B. It is declared as a pointer to A. At compile-time it is the static type that is considered, and the static type is "pointer to A".
Code:
class A
{
private:
virtual void foo(){}
};
class B : public A
{
public:
virtual void foo(){}
};
int main()
{
B b;
A* pA = &b;
pA->foo();
}
What results do you get with this change? I bet it doesn't even compile.
Regards,
Paul McKenzie
-
July 18th, 2013, 08:40 AM
#3
Re: virtual breaks encapsulation in C++?
Originally Posted by Paul McKenzie
[...]
What results do you get with this change? I bet it doesn't even compile.
I agree (though I didn't try it). I wouldn't even have expected the original code from post #1 to compile. And even if it's possible, I consider changing the visibility of virtual functions when deriving questionable in general.
In that original code, it's B that breaks its own encapsulation by making the private member function virtual, thereby allowing the base class (about which, ideally, it shouldn't make any assumptions beyond its public and protected interface) to call it. That's the decisiion of B's designer and he simply wouldn't need to do that if he wouldn't want to for some obscure reason. That's it.
After all, IMO private virtual functions don't make any sense anyway.
[EDIT:] Ok, one acceptable reason for a private virtual function I can imagine is to seal the function with respect to further derivates, i.e. disallowing them to override the function. And then it would be absolutely intended to allow the base class to call that function. I never encountered a design where I really would have wanted to do that, though.
Last edited by Eri523; July 18th, 2013 at 08:52 AM.
I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.
This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.
-
July 18th, 2013, 09:01 AM
#4
Re: virtual breaks encapsulation in C++?
Sutter on public vs private virtual functions ...
http://www.gotw.ca/publications/mill18.htm
-
July 18th, 2013, 10:11 AM
#5
Re: virtual breaks encapsulation in C++?
Originally Posted by Eri523
one acceptable reason for a private virtual function I can imagine is to seal the function with respect to further derivates, i.e. disallowing them to override the function. And then it would be absolutely intended to allow the base class to call that function. I never encountered a design where I really would have wanted to do that, though.
Here is a scenario:
The base class has a public execute() function. This function must call virtual functions f1(), f2(), f3(), in that order. Also f1(), f2(), etc. are customized by the derived classes. How do you, at the very least, make it difficult to do the following:
a) call f1(), f2(), etc. from outside the classes, and
b) calling f1(), f2() in the wrong order of execution as specified by the requirements.
The way this is usually done is to declare f1(), f2(), etc. as private virtuals, and have execute() be a non-virtual public function in the base class. This way the derived classes still have customization, but the execution is controlled by the base class.
Regards,
Paul McKenzie
Last edited by Paul McKenzie; July 18th, 2013 at 12:01 PM.
-
July 18th, 2013, 11:05 AM
#6
Re: virtual breaks encapsulation in C++?
Originally Posted by LarryChen
Obviously when you call pA->foo, it will call foo defined in B. But foo defined in B is private. It is not supposed to be called outside the class B. So it looks like virtual breaks encapsulation.
The interface of B violates the Liskov substitution principle. However, the fact that only the type of pA is considered here saves the day, in a way.
-
July 18th, 2013, 04:30 PM
#7
Re: virtual breaks encapsulation in C++?
Originally Posted by Paul McKenzie
Here is a scenario:
The base class has a public execute() function. This function must call virtual functions f1(), f2(), f3(), in that order. Also f1(), f2(), etc. are customized by the derived classes. How do you, at the very least, make it difficult to do the following:
a) call f1(), f2(), etc. from outside the classes, and
b) calling f1(), f2() in the wrong order of execution as specified by the requirements.
The way this is usually done is to declare f1(), f2(), etc. as private virtuals, and have execute() be a non-virtual public function in the base class. This way the derived classes still have customization, but the execution is controlled by the base class.
Regards,
Paul McKenzie
Thanks for outlining that. When initially reading your post, I considered your example an extension of the Non-Virtual Interface idiom (that I've alreay used myself quite a few times), but after reading the excellent article Philip linked to in post #4 I concluded that it exactly is an application of the idiom.
Now I know my firm belief in private base class member functions being competely invisible to derived clases so they can't be overridden was a misconception that in fact I never questioned since it seemed so logical. So, of course, private virtual functions do make sense. However, most of my virtual functions probably will remain protected, as they've been all the time, since I frequently implement overrides in terms of the base class implentation, applying certain pre-filtering and/or post-processing.
The idea of making the use of the NVI idiom ones default implementation habit definitely seems to be worth another thought.
I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.
This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.
-
July 21st, 2013, 06:42 AM
#8
Re: virtual breaks encapsulation in C++?
Originally Posted by LarryChen
breaks encapsulation.
In my view this feature of C++ rather enhances encapsulation; A is the public interface and B is a hidden implementation of A not to be publicly instantiated.
It would be better if C++ sported a "module" feature but lacking that making all derived implementation classes all private is a good enougth alternative.
Last edited by razzle; July 22nd, 2013 at 07:01 PM.
-
July 21st, 2013, 06:52 AM
#9
Re: virtual breaks encapsulation in C++?
Originally Posted by laserlight
The interface of B violates the Liskov substitution principle.
Well, B violates Liskov only if it's intended as a publicly exposed subtype of A. If the sole purpose of B is to be an anonymous implementation of A it doesn't.
Last edited by razzle; July 21st, 2013 at 09:41 AM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|