[Exceptional C++ Style] Item 17 - Encapsulation

solosnake . solosnake at hotmail.com
Mon Dec 20 12:24:28 EST 2004


>From: Jon Jagger <jon at jaggersoft.com>
*snip*

>>// Case 1 : Encapsulated data.
>>class Case1
>>{
>>public:
>>    const SomeData& GetSomeData()const;
>>private:
>>    const someData_;
>>};
>
>And I'm afraid this example does not convince me. This is not encapsulated 
>data. Sorry but it isn't. It's data that starts hidden but then makes a 
>break for it and escapes (returned by reference from method). The net 
>result is you have code that could be said to somewhat encourage a 
>dangerous style. Viz...
>
>const SomeData & all_bets_are_off()
>{
>    Case1 c;
>    return c.GetSomeData();
>}

>
>
>>
>>// this could also be inlined instead.
>>const SomeData& Case1::GetSomeData()const
>>{
>>    return someData_;
>>}
>>
>>// Case 2 : public const data.
>>class Case2
>>{
>>public:
>>    const someData_;
>>};
>>
>>Is there really an argument for case 2? Case 1 allows all the 
>>functionality required for any usage of case 2, but is safer,
>
>Is it? See above. If the method had returned by value, then things might 
>have been different, but it doesn't...Look at what you have written - a 
>class with one public const data member and no, repeat no, member functions 
>at all. Case2 is a struct in disguise. Now you might, quite legitmately, 
>say but that's just an example, that you wouldn't write that in real code. 
>That in real code you would have some member functions. And I'd agree. And 
>ask for the real example so we can ground this a bit.
>
>Don't get me wrong now. I'm all for encapsulation. For example, size() is a 
>method on the STL containers and that's right and proper. No one is 
>suggesting that size should be a public (non-const) data member. 
>Encapsulation is a principle which if sensibly applied brings tremendous 
>benefits. But if misapplied it can bring more harm than good.

I don't think you are being fair here - the original question was whether 
public const member data was acceptable. I say it is not, and provided a 
simple example of how even the thinnest of wrappers provided a degree of 
usefulness and minimised dependencies on class internals. I was not 
attempting to provide an example of an actual real world class (hence names 
like 'SomeData' and Case1).

To bring this back to the original point - should classes be allowed expose 
member data if that data is const? I still say no. The function of the class 
should be made apparent via its interface, and even if all a class did was 
provide access to some const data, it is still advantageous to wrap this in 
an interface. If there was just a single reason to do this, surely that is 
all it should take to convince you? And there are several:

1) The user of the class depends on the class member functions, which 
guarantee certain behaviours, but allow the implementor freedom of internal 
design.
2) It allows the use of compiler firewalls etc (if data is returned via 
pointer/reference).
3) It allows the member data to be non-const even if the class user sees 
only a const version.
4) The class can be safely changed (to some degree within the design 
parameters) without changing the code that uses it (this is a variant on #1 
really).

Cheers,

Daire





More information about the Effective-cpp mailing list