mutable in C++

I’ve gone back to some refactoring for a few days to solve a problem that has been annoying me for a while. The solution is found in some C++ arcana that I always used to avoid due to porting issues, but now feel confident to try as I have not encountered a bad C++ compiler in a few years now.

Some ‘const’ member functions (those that only want to read and not write to an object) need to make innocuous changes to data members (e.g., a Set object might want to cache its last lookup in hopes of improving the performance of its next lookup, or lock access to an object via a lock object which is a member).

When this happens, the data member which will be modified should be marked as mutable (put the mutable keyword just before the data member’s declaration; i.e., in the same place where you could put const). This tells the compiler that the data member is allowed to change during a const member function.

If your compiler doesn’t support the mutable keyword, you can cast away the const‘ness of this via the const_cast keyword – but this is very very evil and bad things will happen if the moon is in the wrong phase and the cock crows four times. Seriously don’t try it – it will ruin your life. Very few C++ compilers don’t support the mutable keyword. Instead of using const_cast, better to “#define mutable” de-const your conflicting member functions and go through const-chain-reaction-hell till your compiler stops screaming at you.

[Update]

You can’t do this – but I wish you could – only because it would make my scummy design neater.

class MwLockedAddressExclusiveList : public mutable MwIPCCriticalSection  

But really this is an issue with the design. A mutable interface does not make much sense and it would be better that I just add that MwIPCCriticalSection  to MwLockedAddressExclusiveList as a mutable  member. So this is more of a problem of my bad design. I am clearly violating the rules of “HAS-A” vs “IS-IMPLEMENTED-IN-TERMS-OF” and “IS-A”

When designing a class hierarchy, you may face a decision between inheritance (IS-A, IS-IMPLEMENTED-IN-TERMS-OF ) vs. the containment/composition/layering/aggregation (HAS-A) relation.

For instance, if you are designing a  Radio class, and you already have the following classes implemented for you in some library:  Dial, ElectricAppliance.

It is quite obvious that your Radio should be derived from  ElectricAppliance. However, it is not always obvious that  Radio should also be derived from Dial.

How to decide?

You can check whether there is always a 1:1 relation between the two, e.g., “do all radios HAVE one and only one dial?” You may realize that the answer is “no”: a radio can have no dial at all (a transmitter/receiver adjusted to a fixed frequency) or may have more than one (both an FM dial and AM dial). Its always important to use your imagination to fully flesh out the possibilities. 

Hence, your  Radio class should be designed as HAS Dial(s) instead of being derived from it (IS-A) . Note that the relation between  Radio and ElectricAppliance is always 1:1 and corroborates the decision to derive  Radio from  ElectricAppliance as a Radio IS-An ElectricAppliance.

When you write software, you deal with two worlds. You deal with the world you want to model, the outside world. You also deal with a world that exists only inside the software, which involves just getting the code to work. HAS-A corresponds to something in the real world. A Radio HAS Dials or a Person HAS Friends. HAS-A corresponds to the application domain. IS-IMPLEMENTED-IN-TERMS-OF never exists in the real world; it is part of the implementation domain. So you couldn’t say a Radio IS-IMPLEMENTED-IN-TERMS-OF Dials. A Radio HAS Dials. But you could say the Radio IS-IMPLEMENTED-IN-TERMS-OF a List of Components. There’s no List in the real world. The List only exists inside the software. So HAS-A is a relationship between classes that exists in the application domain. IS-IMPLEMENTED-IN-TERMS-OF is a relationship between classes that exists in the implementation domain.

There are several schools of thought of this – much like schools of kung-fu. I subscribe to the following.

If you find yourself describing relationships as “HAS-A” Then you want to use simple composition and aggregation

If you find yourself describing relationships as “IS-A” Then you want to use public inheritance. You want to declare to the world that it conforms to a certain aspect of your model.

If you find yourself describing relationships as “IS-IMPLEMENTED-IN-TERMS-OF” then you should use private inheritance. You want to give an object an ability or behavior in the process of implementing it – You want how you did it to remain secret so that if you change your mind, nobody will notice.

It is generally thought that protected falls into its own area and nobody has yet figured out how to use it a way that conveys any useful semantic meaning that gives a programmer that happy-feel-good -rush that you get with everything in its place and a place for everything. One possible interpretation is “a combination of IS-IMPLEMENTED-IN-TERMS-OF and IS-A  but for ‘my derived classes only'” – This has the effect of controlling the degree of polymorphism. Using protected can make reading the relationships within your code ambiguous – but it does have its place in the C++ pantheon of model glue.

I should have listened to my Mother’s advice and become a brain surgeon.

http://www.devx.com/tips/Tip/5809

http://www.artima.com/intv/meaningP.html

http://www.parashift.com/c++-faq-lite/

http://cpptips.hyperformix.com/cpptips/prot_inher2

 

Advertisements

About metawrap

CTO Massive Interactive. Ex Computer Whiz Kid - Now Grumpy Old Guru.
This entry was posted in C#. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s