Given that the *
operator returns a reference to the object, and since ->
is basically a shorthand for (*a).b
, why does C define a separate overload? To me it seems like you would want to keep *
and ->
in sync at all costs to avoid weird bugs, but the * operator already works to define ->
as well.
EDIT: for clarification, my reasoning is that if the implementation of ->
is just (*a).b
. if we just overloaded the *
operator and treated ->
basically like a macro to the (*a).b
form, then the overloaded *
would apply to the new expression and we would get an overloaded ->
for free
CodePudding user response:
Originally, C has not put any rules on which operators you define, or whether you define them in a logically symmetric manner. You can choose to implement just 1 comparison operator , or many, though later standards have tried to regularise this somewhat.
A couple of ways you could take advantage of this:
- You may want to stop
*
from being used to get your internal object, and perhaps take its address.
Yes, ->
gets your internal object, but it doesn't leave it in an accessible state, a member must be called.
Effectively, ->
provides better OOP than *
.
Ok, yes, as HBC points out, the object caller can call the method operator->()
directly and get the object, but I would like to think that this would be an obvious code smell in any code review. I mean, you could just reinterpret_cast<> the object bytes into the pointer, if we go down that path.
Of course, yes, if you are going to implement *
, then you might as well implement ->
, but not necessarily vice-versa.
- The other thing you might do is implement
*
to give you a raw blob of data or simple struct, that you might then transmit or store, but->
gives you a manipulator object paired with the data, so adding some object richness to a simple struct. This would be in a case where you can't simply add the richness directly, perhaps because the data was provided by an older C library.
You could even have the simple blob implement some compact c-style nested struct polymorphism, while ->
gives you an equivalent smart manipulator.
In this way ->
has provided a "view" on your data. Potentially that might be confusing, or it might be the obvious way to provide object capabilities to a piece of dumb data, that perhaps still needs to also be accessed as dumb data. All these tools are provided to API definers to use wisely.
CodePudding user response:
The simple answer is - and you'll find it many times with C - why not?
You can see the same for other operators: operator
, operator-
unary and binary; operator<
, operator<=
, operator==
, operator>=
, operator>
, operator!=
, and many others - these are deducible from each other if you use them in the standard meaning. Yet - it's possible to override them.
Now, reason for overriding might differ from project to project: sometimes, you'd like to implement an EDSL and unary *
might have a radically different meaning than ->
; sometimes you'd like to optimize the last bit out of the architecture; sometimes you're porting code that someone copy-pasted from e.g. Java and want to put special checks in ->
, which are unneeded in *
; your reasons might vary.
However, C doesn't enforce one specific 'good' way of doing this. In fact Bjarne himself said (at the C Budapest meetup), he'd like to keep C diverse and allow many programming styles, paradigms. So the language itself doesn't limit you.