Home > Blockchain >  Why does C let you overload the * and -> operators separately?
Why does C let you overload the * and -> operators separately?

Time:08-31

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:

  1. 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.

  1. 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.

  • Related