views:

189

answers:

1

Firstly I'll show you few classes.

class A {
public:
    B * something;

    void callSomething(void) {
        something->call();
    }
};

class B {
public:
    A * activeParent;

    B(A * parent) {
        activeParent = parent;
    }

    void call(void) {
        activeParent->something = new C;
    }
};

class C : public B {
public:
    A * activeParent;

    C(A * parent) {
        activeParent = parent;
    }

    void call(void) {
        // do something
    }
};


A * object;
object = new A;
object->something = new B;
object->callSomething();

My app needs such a structure. When I do callSomething(), it calls B's call() but when B's call() changes the "something" to C, C's call() is triggered and I want to avoid that. How should I do?

+1  A: 

Aside from the design decisions (e.g., cyclical dependencies)...

The only reason A's callSomething() method would call C's call() method from a pointer to B is if the call() method is virtual. To avoid calling C's call() method, here are a couple of options:

  • Don't make the call() method virtual
  • Rename one of B or C's call() method (preferred over the first option)
  • Call B's call() method explicitly

To call B's call() method explicitly:

void callSomething(void) {
    something->B::call();
}
Jason Govig
I need to have call() in all classes that inherit from B. So lets say that I have classes D, E, F. D inherits from B, E too and F inherits from E and I need a common way to call the call(). So first and last options won't help me and nor second one as I need common name of function. Anyway thanks for your answer and I hope that you can help me somehow!
Balon
Hmmm but third option would be useful if..`something->B::call();`B could be that class what `something` is at the moment.
Balon
Do you only ever want to call B's version of the call() method for all instances of a B pointer (whether it's a B, C, D, E, or F)? Or do you just not want to call C's call() method if something is a C object? And is this special behavior only desired for A's call from callSomething(), or all calls to the call() method?
Jason Govig
`And is this special behavior only desired for A's call from callSomething()` yes. I want to be able to call the call() method with one restricton. If `A->something` is a C class, I want to call only C's call method(), if it is B class so I want to call only B's call method(). I've written in my question what happens right now with actual way of calling call() method.
Balon
The problem is here. `void callSomething(void) { something->call(); }` and explicit call would solve this, but something can be whatever so.. I can't actually call it explicitly...
Balon
I think I now know what you are asking for.Let me restate the problem: with your current code, it always calls class B's call() method, even if the something pointer (B*) is pointing to a C object. And what you really want is for callSomething() to call B's call() if something is pointing to a B object, C's call() if it is pointing to a C object, etc. Solution: mark the call() method virtual in the base class (B), i.e. "virtual void call() { ... }", and something->call() will dispatch to C's call() method (if something is pointing to a C object).
Jason Govig
Exactly. It is already virtual in my code, but the problem appears when `something` changes during call(). If `something` is `B` and during `something->call()` I change `something` to `C`, then C's call() is called and I don't want it to.
Balon
I solved this out. Thanks for you help, it helped me a lot ;)
Balon