-1

I'm reviewing some code and I have stumbled many times on examples as described in title. THen this passed object is referenced in calling outside methods from second object, even changed somewhere else and then again used by reference in another methods.

THe weirdest thing is that the second object calls methods from passed first object that created second anyway.

I haven't done similar stuff yet, but I since I am relatively new to C++ I allow possibility that people feel very free in coding with language with so many options...

However, the main question is: is that common practice? Is there any technical reason for not doing such stuff?

I have added a short example:

TypeReturned *ClassB::GetSomething( ClassA *objectA)   
{
        someMethod(wm);

        ClassC *objectC = new ClassC(objectA->method());

        PCS->method(……, &objectA->someMethod(), objectA);
}

This method is called from objectA. First call is quite normal. The second and the third would be more readable to solve with simpe passing needing parameters, not the complete classes and callbacks. I can also say, that those those 2 classes do not really communicate to each other and don't have cross-references.

Kiril Kirov
  • 37,467
  • 22
  • 115
  • 187
poksi592
  • 135
  • 7
  • 7
    I'm not sure I understand what you're saying... can you give a concrete code example? – templatetypedef Mar 11 '11 at 09:27
  • Yeah, I expected somethin like that :) Sorry. So, we have object A that instantiates object B. Object A then calls methodB(A), menaing passes itself to method in class B. THen object B instantiates class C and calls methodC(A), where A is used as reference and something is done with it, then object D ic created (still within object B) where methodD(&A) is called and within this method, A->methodA(xxx) is called. THis happens many times within methodB and A->methodA(...) is called many times: A is sometimes original A and sometimes another A created from some other outside method called... – poksi592 Mar 11 '11 at 09:42
  • 1
    It would be better if you post some real (dummy) code. And it's better to write such things not like comments, just edit your post. It will be more clear and more people will see it. – Kiril Kirov Mar 11 '11 at 09:46
  • For anyone to tell whether what you're looking at is weird you need to be more concrete. It all depends on the class relationships and what the actual methods are, but it's definitely not uncommon. – molbdnilo Mar 11 '11 at 09:47
  • Perhaps main question should be divided into more: is this usual and practical workaround to pass itself to another object in C++? Isn't it very bad practice to call object methods from its callers not have any kind of reccurence logic or parent-child relationship? – poksi592 Mar 11 '11 at 09:50
  • I'm not sure that new code really clarifies matters... Is the answer I posted below along the right lines of what you are trying to ask or have I completely misinterpreted the question? – James Greenhalgh Mar 11 '11 at 10:21
  • @poksi592: To further clarify - what do you mean by recurrence logic? – Rafał Dowgird Mar 11 '11 at 10:45

3 Answers3

0

AFAIK it's perfectly OK technically and happens all the time. Sometimes it's the "best" way and, believe it or not, the clearest way.

  • pete
Pete Wilson
  • 8,610
  • 6
  • 39
  • 51
  • yes, similar question from my side. I have a feeling that programmer is just not having its design prepared and passing whole instances because having the hunch that somethng would be needed from class calling objects not isolating actual parameters and change method signatures . – poksi592 Mar 11 '11 at 10:20
0

I think (Although, I can't tell and am happy to be shown wrong) that what you are describing is a scheme similair to double dispatch (Example in C#). If I am correct you are seeing calls like:

class LivenessPingMessage : public Message {
   public:

    void accept(Controller& c) {
      c.visit(this);
    }
}

class Controller {
  public:

  handleNetworkQueue() {
    while (true) {
      Messages::Message* m = networkLayer->getNextMessage();
      if (m != NULL) {
        m->accept(*this);
      }
    }
  }

  void visit(Messages::LivenessPingMessage* m) {
    //Do something
  }

}

class Message {
  public:
    virtual void accept(Controller& c) = 0;
}

This allows the class Controller to handle messages by calling the virtual accept() method they have. These messages then use the pointer to Controller they have been given to call the overloaded method visit(Message m).

This means that Messages only need to know about Controllers, not any other details about the tasks they are supposed to complete. The Controller contains all the logic needed to deal with the Message appropriately.

It is common amongst people who like double dispatch and is a recognised design model.

Community
  • 1
  • 1
James Greenhalgh
  • 2,401
  • 18
  • 17
0

Perhaps main question should be divided into more: is this usual and practical workaround to pass itself to another object in C++?

It is both usual and practical. Quite often it's the most natural way to achieve something. For example if you want a parent-child navigable from both ends, it's easiest for the parent object to pass itself (this) to the child object after creation so that it stores the reference to parent. Registering self for callback (as in the observer pattern) is another example.

This is useful in general, not something specific to C++.

Rafał Dowgird
  • 43,216
  • 11
  • 77
  • 90
  • This is quite clear to me, but second part was: " Isn't it very bad practice to call object methods from its callers not have any kind of reccurence logic or parent-child relationship?" – poksi592 Mar 11 '11 at 10:51
  • " I can also say, that those those 2 classes do not really communicate to each other and don't have cross-references." Unfortunatelly, there is also no any kind of observer pattern involved. – poksi592 Mar 11 '11 at 10:53
  • @poksi592: Unfortunately, from what you described I am unable to deduce enough to tell. The classes do not really communicate to each other? If this is really the case, they obviously shouldn't call each other methods, but OTOH if they do, they indeed communicate. TLDR: more info needed whether this particular dependency actually makes sense. – Rafał Dowgird Mar 11 '11 at 11:44