* Squeamizh:
Alf said:
[const_cast<...>(this)]
Does the above cause undefined behavior?
No, but (1) it would if you tried to modify the object, because it's
originally declared 'const', and (2) instead of the monstrosity above,
where you expose a data member completely via absurd code, you could and
probably should simply do
[struct]
I agree. The code I posted was simplified in order to clearly express
the root of my concern. Since you brought it up, though, I'd be
grateful to hear if you think I am using the wrong solution for my
problem. I originally had a class declaration that looks like this:
class my_class {
public:
virtual int& get_value() = 0;
virtual const int& get_value() const = 0;
};
my_class does not actually contain an "int value" (hence the pure
virtual getter) because I would like to have a descendant of my_class
("class outer") that contains another descendant of my_class ("class
inner"). inner contains the actual "int value", and outer just
delegates the above two functions to inner.
Ah, design issue. First off, this is a separate issue from the const
overloading issue. This issue is about one class, here 'my_class',
requiring that some other class, here 'inner', provides a member of a
given type (because of the references).
I.e., that one class dictates the /implementation/ of another class.
That's generally UnGood.
At the very least, try to separate implementation from interface, by
class MyClass
{
public:
virtual int value() const = 0;
virtual void setValue( int v ) = 0;
};
But note that this interface is essentially an interface to a /global
variable/ -- where I'm using the term "global" very loosely, but the
point is that the value can be modified from anywhere, and in the end
someone will have to resort to painful debugging and searching of tons
of code to establish where the heck the final useful value comes from,
or where the code is that puts in a very much less than useful value...
The problem is the public setter function.
The solution depends strongly on what the actual design is all about,
but generally, most designs where the client code changes values (this
makes it all but impossible to maintain any class invariants) can be
recast as more reasonable designs where the client code just states the
effects or results wanted -- operations, not raw data.
[moved this paragraph up here from further down in the text]
This may still seem absurd, but it is still a bit simplified. There
are actually eight or so getters like the above, and several different
"outer" and "inner" classes that all inherit my_class.
Ouch. Those eight or so values seem to be strongly related, and if they
aren't, they should be, to appear in the same interface. Why not pack
them in a class and provide just /one/ set-and-get pair, or better yet,
as mentioned above, a single getter function 'T const& value() const',
or even better better yet, as mentioned above, operations, not raw data?
OK, I know one reason: an unreasonable psychotic project lead who
absolutely don't want any such "fancy" stuff, it /must/ be spaghetti,
visually identical in texture (yes) to the rest of the code.
But apart from that?
However, I don't want
outer to have to override both a non-const version of get_value and a
const version of get_value. I would like to avoid the tediousness of
overriding twice as many getters in all these classes.
Note: at least for primitive types such as 'int' those aren't really
getters, they're setters camouflaged as getters, because they return
references.
But when you have a getter where the constness of the result should
depend on the constness of *this, and the logic of that getter is
complex, deferring to a common implementation and using const_cast is
all right (the common implementation can be templatized in order to
avoid the cast, but that's very seldom worth the coding investment).