1

The current situation is this: I am going through some code re factoring

enter image description here

If you look at the image the current situation is that I have a virtual method setData(int ID); now we want to change that to a virtual method setData(dataObj aObj);

But doing so, is a long process since, our foo object has been inherited by tons of classes. So, we want to gradually make the code change.

As such, what I need to do is to check if one of the inherited classes has implemented setData(dataObj aObj) call that class, else call the other previous function signature setData(int ID); The problem is further complicated by the fact that, FOO class provides a default setData(int ID) previously and not all classes that inherit from FOO thus may/may not need to implement setData and their implementations do vary wildly.

I have already looked at How to Check if the function exists in C/C++ unfortunately, that does not answer my questions.

In some of the posts I have seen people use templates, that's not an option for me, since this needs to be done at runtime. The other options seems to suggest linking /mangling tricks with GCC etc. I need to build my code to be platform and compiler independent. So that's not an option either.

Any more suggestions, the only possible close solution seems to be https://stackoverflow.com/a/8814800/1376317 But I am really not sure how to implement this in my workflow, or whether this is even relevant to my problem.

Community
  • 1
  • 1
thassan
  • 391
  • 3
  • 15
  • You cannot. Instead, fix your overly complicated design (which is funny; you mentioned it yourself: “the problem is further complicated by the fact that …”). –  Dec 26 '13 at 23:46
  • Out of curiosity: What is the reason this has to happen at runtime? –  Dec 26 '13 at 23:59
  • Is that mspaint horror that I see? Just for your own sanity, check [inkscape](http://www.inkscape.org/en/) out for such diagrams. In the very least, after you realized the texts in the final image are too small, you can almost instantly resize them. – Shahbaz Dec 27 '13 at 00:04
  • Also, to be sure you are not experiencing the [xy problem](http://meta.stackexchange.com/q/66377/169090), please provide a little bit of details of what you are actually trying to do and why you have chosen this particular (impossible) solution. – Shahbaz Dec 27 '13 at 00:07
  • From where `ID` and `aObj` come from in `Init` method ? – Jarod42 Dec 27 '13 at 00:14
  • @rightfold - the whole point of this workflow is to ensure that we make incremental changes to the existing design. If I go and try to change the entire design at one shot, more chances to make mistake and will take forever. Often times , while re factoring, one does make an alternative shell around existing code.; @Nabla thanks for editing. And the reason, why I cannot have this happen in runtime , is because the `bar`, `baz` objects are only created on demand due to user inputs, so its only at runtime, I know which kind of `Foo` object (`bar` or `baz`) is created – thassan Dec 27 '13 at 08:20

2 Answers2

2

You may do something like:

class Foo
{
public:
    // Old interface
    virtual void setData(int ID) { /* Old default implementation */ }

    // New interface
    virtual void setData(dataObj aObj) { /* New default implementation */ }

    void init() {
        if (useOldInterface()) {
            setData(ID);
        } else {
            setData(aObj);
        }
    }

private:
    // temporary method to be removed once all derived classes return false.
    virtual bool useOldInterface() const { return true; }
};

And change progressively derived classes by adding

virtual bool useOldInterface() const override { return false; }

and appropriate void setData(dataObj aObj).

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • I am not an expert on design patterns. But is there some design pattern, delegation, functor approach that would let me do this either more elegantly or without touching the derived classes? From the onset of what I have seen, that is most probably not possible. @Jarod42, I will probably take this answer if nothing else comes up. seems to be the only option for the lowest amount of incremental code change at the derived classes part, to accomplish what I am trying. – thassan Dec 27 '13 at 08:40
  • @thassan: if you have already a **Visitor** in place, you may use it. Else you may use `if` cascade with `dynamic_cast` for each derived classes, but it it less elegant, but doesn't touch the hierarchy. – Jarod42 Dec 27 '13 at 09:55
1

If modifying dataObj class is an option, and creating and destroying dataObj objects are not too expensive, then you can consider the following. I don't particularly like it but as far as short term hacks go, I have seen worse...

class dataObj
{
int x;
public:
    int getID(void) const { 
        std::cout << "dataObj::getID " << std::endl;
        return x;
    }
    dataObj() : x(0){}
    ~dataObj(){}

};
class Foo
{
public:
    // Old interface
    virtual void setData(int ID) {
        /* Old default implementation */
        std::cout << "Foo::setData int" << std::endl;
    }

    // New interface
    virtual void setData(const dataObj& aObj) {
        /* New default implementation */
        std::cout << "Foo::setData dataObj" << std::endl;
        setData(aObj.getID());
    }

};

class A : public Foo
{
public:
    virtual void setData(int ID) {
        /* Old default implementation */
        std::cout << "A:: setData int" << std::endl;
    }

};

class B : public Foo
{
public:
    virtual void setData(const dataObj& aObj) {
        /* Old default implementation */
        std::cout << "B:: setData dataObj" << std::endl;
    }

};

int main(int argc, char* argv[])
{
    A a;
    B b;
    dataObj d;
    Foo* pa, * pb;
    pa = &a;
    pb = &b;
    pa->setData(d);
    pb->setData(d);
return 0;
}
rakeshdn
  • 135
  • 1
  • 7
  • thanks but this is not exactly my situation. If I look at what you have proposed you have class A now also inherits `setData(dataObj)` previously it used to override `setData(int ID)` and . Now `setData(dataObj)` can be called through inheritance. But for me that is simply not an option. If we have previously had to override the `setData(int data)` for class A inherited from class `Foo`, that means class A needed special handling and even now `setData(dataObj)` will also need to be overridden , since it will need special handling. – thassan Dec 27 '13 at 08:53
  • So this approach on getting the default behavior from base will not work., – thassan Dec 27 '13 at 08:53