jcoder
jcoder

Reputation: 30035

Const member function when operation has clear side effects

Imagine I have a class "Window" with a member function "show" which causes the underlying window to become visible on the screen.

Because I'm calling an underlying windows API to achieve this I'm not in any way altering the state of my "Window" object and yet clearly there is a large, obvious change in state of my window caused by calling this ( a window appearing on the screen and being able to be interacted with by users)

So I should declare my function as -

void Window::show() const;

because as far as the Window object is concerned this function doesn't change any state and therefore can be called on "const Window" objects. But somehow that doesn't seem right as calling that function clearly in some sense changes the state of the object.

Upvotes: 4

Views: 1608

Answers (5)

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145279

Usually you have this situation:

  • For each API window, there is at most one C++ window object.

  • A C++ window object is not copyable (including that it is not cloneable).

For this case it is possible to use const in the C++ object interface, so as to let client code offer no-state-change guarantees by e.g. declaring some parameter as const.

However, as soon as one or both constraint are removed, it becomes a futile and meaningless exercise. Consider, for example, removing the second constraint, making the C++ objects copyable. That might seem to make sense, treating the C++ objects almost like shared_ptr instances (except for destruction).

But any const shared_ptr can be copied to a non-const one, so any non-const methods can easily be called. For example, shared_ptr::get is a const method so that it can be called on a const shared_ptr object. But its result is T*, i.e. no const propagation to the result, because even if it was T const* it would not really restrict the client code: the client code could just copy that const shared_ptr to a non-const one, and then call get on the non-const instance.

Still, with both gurantees above in place the fact that const (or in your case the absence of const) can be used in a possibly useful way to restrict operations on the referred API window, does not mean that it is necessarily a good idea to do it.

In particular, objects that represent windows are usually event receivers, and in my experience, events do not mix very well with const.

However, most programmers are used to pure inspectors being const. And for that usage, just improving the readability of the code, I would recommend const methods. For example, an inspector that returns the window size, would in my view better be const than non-const.

Upvotes: 0

James Kanze
James Kanze

Reputation: 153919

This is the classical logical const vs. bitwise const question. It was debated hotly back when I was learning C++ (early 1990's), but since then, I think there is a consensus in favor of logical const: if the logical state of an object changes, then the function should not be const (even if the compiler would allow const), and if the logical state doesn't change, then the function should be const (even if you need mutable or to cast away const to do; e.g. a cached result of a computation).

In the specific case of Window::show, it's hard to say. Is the fact that the window is being displayed part of its "logical state" or not.

Upvotes: 7

Mark Ransom
Mark Ransom

Reputation: 308206

If you expect to call the function using a const pointer or reference, you must mark the function const to be able to do so. Otherwise it's completely up to you.

Edit: Giving this some more thought. Your object probably contains a handle to an OS window, and this handle can be passed to OS functions. The handle doesn't really have a concept of constness so it's an impedance mismatch with C++, but the function you pass it to will either be querying a window property (const) or modifying the window in some way (non-const). It would be useful for your object to enforce the constness concept even though the OS does not.

Upvotes: 2

Jon Purdy
Jon Purdy

Reputation: 54979

What you’re probably grappling with is that C++ has no notion of purity, that is, whether or not a function has side-effects. const member functions only make the promise that the state of the object itself will not be modified.

However, some objects logically consist of more state than what the instance actually contains. This comes up very often when an object’s role is to interact with state managed by another library—especially a GUI library.

Therefore, while show() can incidentally be marked const, it logically should not be. If it were truly const, then you would expect a function such as is_visible() to return the same value both before and after the call to show(), and clearly that is not the case.

In other words, const functions are those that change nothing about the object that you can observe through its public interface. That’s the reasoning behind, for example, marking some member functions const but using a mutable member to do internal bookkeeping.

Upvotes: 8

Puppy
Puppy

Reputation: 146940

It may not change any state of any variable physically held within the Window object, but it does change the state of the thing the Window represents, so I would definitely argue non-const.

Upvotes: 4

Related Questions