views:

97

answers:

2

I have a few questions regarding differentiation between const and non-const versions of methods in C++.

Example:

      MyObject* MyClass::objectReference()
const MyObject* MyClass::objectReference() const

My questions are:

  1. Is there any way at all to differentiate between which version of the method is called manually? Or is it fully/completely automatic and if so what are the precise rules for determining which version is to be called?
  2. Related to (1), if you cannot differentiate between calling the const vs the non-const version, it's therefore impossible to call one version of a method from the other to prevent duplication?
  3. How to create a link to one version or the other in the documentation of one of the methods using doxygen? (e.g. "const version of myMethod()." or "non-const version of myMethod().") Found this out myself - just add or omit " const" at the end of the method signature.
+5  A: 

I don't know about doxygen; though here is what I know.

  1. If there's only a non-const version, it simply can't be called on a const object.
  2. If there's only a const version, it can be called on both const and non-const objects.
  3. If there's both, the non-const version will be called on non-const objects, and the const version will be called on const objects.
  4. If you want to explicitly call the const one, you have to cast your object to a const reference of itself: static_cast<const MyClass&>(myObject).objectReference();
zneak
Would you use `const_cast` instead?
Duracell
@Duracell: I'd rather use `const_cast` only for removing the `const` modifier, since `static_cast` does a great job at adding it.
zneak
@Duracell @zneak: This is a good use case for [an `implicit_cast` function template](http://stackoverflow.com/questions/868306/what-is-the-difference-between-static-cast-and-implicit-cast/869597#869597).
James McNellis
A cast is unnecessary. Best to use casts for narrowing conversions, adding `const` is a widening conversion. Instead, just initialize a reference, as in `const MyClass constmyObject.objectReference();` This can't do anything unsafe by accident.
Ben Voigt
@James: Ah, I didn't know boost had that. Thanks!
bcat
@zneak Great answer, thanks!
Jake Petroules
@Ben Voigt That's a good point...
Jake Petroules
@Jake: James's suggestion of `implicit_cast` is a neatly wrapped way of expressing the initialize-a-const-reference method. Only downside is an extra header file from boost.
Ben Voigt
For completeness it might be of interest that function pointers can also be used to differentiate the two: `(void (X::*)() const)` - useful e.g. for disambiguating with `bind()` et al.
Georg Fritzsche
+1  A: 

While, calling the non-const method on a const instance probably isn't wise. If you want to call the const method on a non-const instance, however, just use a cast. See the following program for an example:

#include <iostream>

class ConstTest {
public:
  void cows() const {
    std::cout << "const method call" << std::endl;
  };

  void cows() {
    std::cout << "non-const method call" << std::endl;
  }
};

int main() {
  ConstTest ct;

  ct.cows();                                 // Prints "non-const method call"
  static_cast<const ConstTest &>(ct).cows(); // Prints "const method call"
}
bcat