torleif wrote:Code: Select all
static const genStruct Foo(){}; // Other programmers seem to use this
I'll assume that you mean some method other than Foo(), since constructors can't have qualifiers or return types.
Whether this is useful depends on whether genStruct is a value or a reference type. If it's a value type, (e.g. int, or a class/structure returned by value rather than by reference) then there's no point in returning a const version, since it's just dumped on the stack and the caller will be taking a copy of it anyway, and you can't effect their version of it.
However, if you're returning a reference type, i.e. a pointer (e.g. int *) or a reference (e.g. genStruct &) then const is useful, as it stops(1) the caller from modifying the thing that you are returning a reference so.
(1) Except it doesn't really...
Code: Select all
class GotSome
{
public:
// These methods are static, which means that you don't need an instance
// of GotSome to call them on. You can just call GotSome::getSome()
// and get returned a pointer to some.
// Note that the pointer/reference are not constant, but the thing that
// they point/refer to is const.
// This means that the caller can't - or rather, that it shouldn't -
// change the value of "some" using these methods, they can only get it.
// Because these are static methods, the methods themselves can't be
// declared const. This would be meaningless, since they don't have
// an object to be called on.
static const int * getSome(void) { return &some; }
static const int & getSomeMore(void) { return some; }
// These are instance versions of the above methods. That means that
// they are not declared static, so they require an instance of GotSome.
// You can't call GotSome::getSomeInstance(). Instead, you need to do (e.g.):
// GotSome aSome;
// const int * something = aSome.getSomeInstance().
//
// The methods themselves are declared const. This tells that compiler that
// calling them won't result in the object being altered; or at least
// not within the method body.
const int * getSomeInstance(void) const { return &some; }
const int & getSomeMoreInstance(void) const { return some; }
private:
static int some;
};
// define the static member, and set its initial value.
// Now, because all the methods that access this return a reference to const,
// it shouldn't be possible for this to change.
int GotSome::some = 1066;
int main()
{
// All as it should be
const int * theInt = GotSome::getSome();
(void)printf("%d\n", *theInt);
// *theInt = 1314; // The compiler won't let us do this, as theInt points to a const int.
// Unfortunately, const is more a guidelines than a rule, and the caller can
// just brutally cast it away.
GotSome aSome;
int & theConstIsALie = const_cast<int &>(aSome.getSomeMoreInstance());
theConstIsALie = 1314;
// Let's just be absolutely sure that this has changed the class member
int * liesDamnLies = const_cast<int *>(aSome.getSomeInstance());
(void)printf("%d\n", *liesDamnLies);
// Thus ends the lesson on the uses and limitations of const.
return 0;
}