views:

128

answers:

2

I'll use the following (trivial) interface as an example:

struct IObject
{
  virtual ~IObject() {}

  virtual std::string GetName() const = 0;
  virtual void ChangeState() = 0;
};

Logic dictates that GetName should be a const member function while ChangeState shouldn't.

All code that I've seen so far doesn't follow this logic, though. That is, GetName in the example above wouldn't be marked as a const member function.

Is this laziness/carelessness or is there a legitimate reason for this? What are the major cons of me forcing my clients to implement const member functions when they are logically called for?


EDIT: Thanks for your responses everyone. I think it's pretty much unanimous: laziness/ignorance is the reason for what I'm seeing.

+7  A: 

Is this laziness/carelessness or is there a legitimate reason for this?

The former. If you really haven't seen any code which does this right, get a new job immediately.

What are the major cons of me forcing my clients to implement constmember functions when they are logically called for?

It allows the compiler to discover common bugs at compile-time. (Nothing better than errors discovered at compile-time. Everything that fails on your desk, won't fail at the client's site.)


More than ten years ago, shortly after I joined a new company and got to hacking at one of their projects, I found that a method that should have been const wasn't, preventing some of my const-correct code to compile. I considered just casting my const away and get on, but I couldn't myself bring to do this.
So I made the method const - just to discover that it called other methods, which should have been const, too, but weren't either. So I changed them as well - just to discover...
In the end, I spent several days hunting through all of the project, adding const left and right.
Co-workers laughed at me - until I showed them some of the bugs the compiler had discovered due to me adding const. Interestingly, a few long-standing bugs nobody had ever taken the time to thoroughly investigate were not reproducible anymore either, after that.

sbi
+1 There is nothing more soul destroying than retro-fitting const correctness to non const correct code.
anon
@Neil, so right - the cascading effects turn into a waterfall of sorrow.
Mark Ransom
Ugh. I can only imagine the ripple effect in a large code base...
58gh1z
I think we've all been there.
Noah Roberts
I wish I could give you another +1 just for the war story.
Mark Ransom
+9  A: 

I think it's laziness/carelessness. GetName() should have no effect on the object's state, and the contract of IObject should state that fact explicitly.

If the inheriting class was somehow forced to make GetName() have (hidden!) side effects, they could always declare the corresponding fields as mutable.

Thomas
I think people forget that 'const' isn't meant to say that nothing about the internal state of the object should change, but that nothing about the external state should. I should be able to store a copy of an instance, call the const function, and the original and copy should still compare equal. Assuming equality actually means equality anything else can change.
Noah Roberts
@Noah Roberts: Also imagine thinks like caches. Changing a cache does not change the external state and is safe in const methods.
rstevens
+1 for mentioning `mutable` and the reasons.
Thomas Matthews