views:

138

answers:

8

Hi, I have a program and many of its classes have some operators and methods with the keyword const like the followings:

operator const char* () const;
operator char* ();
void Save(const char *name) const;
void Load(const char *name);

First: what does it mean const at the end of the method declaration?, is it the same like putting it at the beginning?

Second: Why would be a const version and a no const version of operator() needed?

Thanks in advance.

+2  A: 

Member function constness. It means the function can not(*) modify any of your member variables. It's like putting a const in front of all your member variables for this one function call. It's a good guarantee for the clients of your class and may also aid in compiler optimisations.

(*) - see also the keyword mutable.

DanDan
+8  A: 

First: what does it mean const at the end of the method declaration?, is it the same like putting it at the beginning?

No. A const at the end means that the method may be called on objects that are declared const. A const at the beginning means that the returned value is const.

Second: Why would be a const version and a no const version of operator() needed?

The non-const version returns a char* which is not const. By modifying this char* you could then in fact modify the object (assuming the char* is a member of the object).

Since this is not allowed for const objects, there's an overload of operator() for const objects, so that a const char* is returned, so the object can't be modified through it.

sepp2k
Ok, I take my answer back, yours is much more clear.
Simon Steele
+1  A: 

Putting const at the end of a method declaration is stating that the object itself, or this, is const instead of the return type.

C++ allows methods to be overloaded on const for complicated reasons. Not enough space to go into full detail here. But here are a couple of short ones.

  • Ocassionally there is value, or flat necessity, in having a method behave differently when it is called from a const type. The most straight forward example is when you want to return a const value from a const method and a non-const value from a normal method.
  • Whether or not this is const dramatically changes the binding of the internal method. To the point that it would essentially become two different method bodies. Hence it makes sense to break it up into 2 different methods.
JaredPar
+1  A: 

'const' at the end tells the compiler that this method does not change any member variables - that it is safe to call this method on const instances. So, Save could be called on a const instance, since it won't change that instance. Load on the other hand, will change the instance so can't be used on const instances.

The const version of operator() passes back a const pointer, guaranteeing the buffer passed back won't change. Presumably that's a pointer into a instance variable of the class. For non-const instances, the other operator() passes back a non-const pointer. It would have to be a pointer to some memory that even if written to, wouldn't change the contents of the instance.

Also, look up the 'mutable' keyword sometime. Understanding that will help you understand this idea of const-correctness.

Graham Perks
A: 
  1. Const at the beginning applies to the return value. Const at the end applies to the method itself. When you declare a method as "const" you are saying that you have no intention of modifying any of the member variables of the class in the method. The compiler will even do some basic checks to make sure that the method doesn't modify member variables. The const in the return value prevents the caller from modifying the value that is returned. This can be useful when you return pointers or references to data managed by the class. This is often done to avoid returning copies of complex data which could be expensive at run time.

  2. The reason you have two different operators is that the "const" version returns a const pointer to what is probably data internal to the class. If the instance of the class is const, then chances are you want the data being return should also be const. The "non-const" version just provides a method that returns a modifiable return value when the caller has a non-const instance of the class.

Torlack
+1  A: 

One note in addition to the other answers: there is no operator() in your example.

operator const char* () const;
operator char* ();

are conversion operators, which mean that objects of the class can be implicitly converted to C-style strings, like

void f(const MyClass& x, MyClass& y) {
  const char* x_str = x;
  char* y_str = y;
}

A declaration and usage of operator(), which means you can use an object of the class type sort of like a function, would look like:

class MyClass {
public:
  const char* operator() (int x, int y) const;
  // ...
};

void g(const MyClass& obj) {
  const char* result = obj(3, 4);
}
aschepler
+1  A: 

If you're looking for a great resource on C++ (including tips on using const correctly) try "Effective C++".

A useful site about this: JRiddel.org

In C++ when you declare a method const by putting it AFTER the method signature you are asserting that "This method will not change any non-mutable instance variables in the object it is being called on."

The const before the return value (e.g. the const in: operator const char*...") is declaring that it only returns a variable pointer to a const char*. (You may not change the contents of the char* but you can re-assign the pointer.) If you wrote "const char* const ..." it would be a constant pointer to constant characters. (The const comes after the star).

The multiple versions are useful so the compiler can understand this:

const char* my_const_var = <object_name>();
char* my_var = <object_name>();

Chris

Cpfohl
A: 

You should refer to the "HIGH·INTEGRITY C++ CODING STANDARD MANUAL" for knowing when it is recommended to use the const modifier for class members:

High Integrity CPP Rule 3.1.8: Declare 'const' any class member function that does not modify the externally visible state of the object. (QACPP 4211, 4214)

Justification: Although the language enforces bitwise const correctness, const correctness should be thought of as logical, not bitwise. A member function should be declared const if it is impossible for a client to determine whether the object has changed as a result of calling that function. The 'mutable' keyword can be used to declare member data which can be modified in const functions, this should only be used where the member data does not affect the externally visible state of the object.

class C 
{ 
public: 
     const C& foo() { return * this; }    // should be declared const 
     const int& getData() { return m_i; } // should be declared const 
     int bar() const { return m_mi; }     // ok to declare const 
private: 
int m_i; 
mutable int m_mi; 
};

Reference Effective C++ Item 21;Industrial Strength C++ 7.13;

ArceBrito