4

When I go thru the code written by collegue, in certain place, they use:

this->doSomething(); //-->case A
doSomething(); //-->case B

In fact I'm not sure about the great usage of *this pointer...:(

Another question with argument matching:

obj.doOperation();  //-->case C
(&obj)->doOperation(); //-->case D

In fact both cases are performing the desired operation, is it simply a way to make the code look more complex?

What is your recommendation on the above two question? When is the appropriate time to use them and why?

rekire
  • 47,260
  • 30
  • 167
  • 264
wengseng
  • 1,330
  • 1
  • 14
  • 27

3 Answers3

5

This is not an answer to your question, but a note that both fragments may do different things:

namespace B { void doSomething() {} }

struct A {    
    void f()
    {
        using B::doSomething;
        this->doSomething(); // call A::doSomething
        doSomething(); // calls B::doSomething
    }

    int a;
    void g(int a)
    {
        this->a = a; // assigns argument to member
    }

    A* operator & () { return this; }
    void doOperation() {}
    void doSomething() {}
};

void g(A &obj)
{
    obj.doOperation();  // calls A::doOperation directly
    (&obj)->doOperation(); // calls A::operator & first
}
Yakov Galka
  • 70,775
  • 16
  • 139
  • 220
3

Cases B and C are always the appropriate way. Cases A and D are equivalent and do nothing different.

A few exceptions to that:

  • If the class has an overloaded operator& that does surprising things, then case D could do something different that C. Actually having classes which do this is not recommended, since it would be confusing.
  • If there is a local variable doSomething (or something else of that name in the local scope), then A would refer to a different doSomething than B. Again it isn't recommended to get yourself into such a situation, better give different names to different things.
sth
  • 222,467
  • 53
  • 283
  • 367
1

C and D are different. If doOperation is virtual, case D will perform the virtual call, case C will perform a non-virtual call if obj is not a reference. This assumes however that operator& and operator-> have not been overloaded.

I tend to use A over B since there may be a local doSomething identifier. Inside template code, things may get worse (although I can't come with a precise example right now). It is a good habit to take.

Alexandre C.
  • 55,948
  • 11
  • 128
  • 197
  • "non-virtual call if obj is not a reference" — Hmmm.... Can there be a difference between virtual and non-virtual call if obj is not a reference? Isn't it get resolved to the same function? – Yakov Galka Sep 29 '10 at 16:02
  • @ybungalobill: nope. if `obj` is a variable of class `C`, `obj.doSomething()` will always resolve to `obj.C::doSomething()`. If `obj` is a reference, it will perform the virtual dispatch. – Alexandre C. Sep 29 '10 at 16:03
  • If obj is a variable, virtual call `(&obj)->doSomething()` will get resolved to the same function as the non-virtual call `obj.doSomething()`, but one call is virtual and the other is non-virtual I guess :) – Maciej Hehl Sep 29 '10 at 16:24