开发者

How to remove unwanted functions from interface

I have an interface class MyFunction. There are three functions in this class with the following signatures:

virtual bool Eval(int& iReturnVal, size_t szArgumentCount, list<Param> lParameterList) = 0;
virtual bool Eval(double& dReturnVal, size_t szArgumentCount, list<Param> lParameterList) = 0;
virtual bool Eval(char*& zReturnVal, size_t szArgumentCount, list<Param> lParameterList) = 0;

Now, any implementation of MyFunction will only need to implement one of these functions depending on what type of value it needs to return. But I'll have to implement all 3 functions even if the other two functions are like this:

virtual bool Eval(double& dReturnVal, size_t szArgumentCount, list<Param> lParameterList){return false;}

which doesnt look so good. Or, I can declare all three functions like this in the interface:

virtual bool Eval(int& iReturnVal, size_t szArgumentCount, list<Param> lParameterList){return false;}
virtual bool Eval(double& dReturnVal, size_t szArgumentCount, list<Param> lParameterList){return false;}
virtual bool Eval(char*& zReturnVal, size_t szArgumentCount, list<Param> lParameterList){return false;}

Which also looks ugly. What is the less ugly of these two? Or is there a better way to do this?

EDIT:

On D Krueger's method :

#include <iostream>

using namespace std;

class Base
{
    public:
        template<typename T>
            void F(T){cout << "Type T" << endl;}
};

class Imp : public Base
{
    public:
        template<int>
            void F(int){cout << "Type int" << endl;}
};

int main(int argc, char** argv)
{
    Base* pB;
    Imp oI;
   开发者_高级运维 pB = &oI;

    pB->F(1);
}

Looks like specialization does not apply across classes though derived. As template functions can't be virtual, this is a hopeless situation it seems.


Since there is a one-to-one mapping between the types used in Eval() and the number of implementations, a template member function should work.

class MyFunction {

    template <class T>
    bool Eval(T& returnVal, size_t szArgumentCount, list<Param> lParameterList) 
        { return false; }
};

Then implement the specializations for the types that shouldn't return false.

This requires only the single generic implementation to return false and the three implementations that would be needed in any case.


It's a sign that your interface-design could need to be refactored, when the classes implementing the interface did not need the whole amount of methods in it. Perhaps you could divide this interface into 3 interfaces.

Another possibility would be to create a wrapper-interface from that, which returns default values for the unneeded 2 methods. But in this case you would end up with 3 interfaces as well (and the original parent-interface -> 4 interfaces total). This solution would be acceptable if you have no possibility of changing the original interface.


I think you might be better off declaring a single pure virtual method to override, but have it return a discriminated union or variant/any type in that first argument. Then each derived class can return the type it wants. With your current way, you were going to need to make a decision on which method to call. With a discriminated union, you'll only call the one method, but make the decision about what to do with it after it returns.

double dd;
int ii;
char* ss;
switch (ptr->type) {
    case DOUBLE:  ptr->Eval(&dd, ...); break;
    case INTEGER: ptr->Eval(&ii, ...); break;
    case STRING:  ptr->Eval(&ss, ...); break;
}

becomes something like:

double dd;
int ii;
char* ss;
variant vv;
ptr->Eval(&vv, ...);
switch (vv.type) {
    case DOUBLE:  dd = vv.dd; break;
    case INTEGER: ii = vv.ii; break;
    case STRING:  ss = vv.ss; break;
}

Obviously I've skipped the error checking and the like, but it's pretty similar to what I think you're planning to do.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜