views:

107

answers:

3

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?

+5  A: 

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
}
ybungalobill
And if you'd overloaded `operator->`, it would also call that in the second example!
Oli Charlesworth
The former is a possible argument against using `using`!
Oli Charlesworth
@Oli: "if you'd overloaded ..." no. It would be called if I'd write `obj->doOperation()`. "The former is a..." it's a very weak argument.
ybungalobill
@ybungalobill: Good point on `operator->`. Regarding `using`, I'd say it's a fairly canonical argument; cluttering up the local namespace which then leads to confusion, rather than explicit disambiguation (i.e. `B::doSomething()`).
Oli Charlesworth
@Oli: Agree in this situation, but not against using `using` in general.
ybungalobill
+3  A: 

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
+1  A: 

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.
"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?
ybungalobill
@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.
Maciej Hehl