Reputation: 30035
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
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
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
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
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
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