2010-10-21 26 views
5

我有一个接口类MyFunction。有三种功能于此类具有以下特征:如何从接口中删除不需要的功能

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; 

现在,MyFunction任何的实现只需要实现取决于它需要返回值的类型,这些功能之一。但是,即使其他两个功能是这样,我也必须实现所有3个功能:

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

这看起来不太好。或者,我可以在界面中声明所有这三个功能:

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;} 

这看起来也很丑陋。这两个比较丑陋的是什么?还是有更好的方法来做到这一点?

编辑:

在d克鲁格的方法:

#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); 
} 

看起来专业化不能跨类申请,虽然的。由于模板功能不可能是虚拟的,这看起来是无望的。

+2

也许你正在寻找类似于'boost :: variant '的参数的单个函数。请致电 – GManNickG 2010-10-21 04:51:56

+0

。 :)。无法使用它。我想要我可以自己建立的东西。 – nakiya 2010-10-21 04:54:29

+1

如果您的界面具有其他纯虚拟功能,请使用第二个。你不会因为拥有更纯粹的虚拟功能而获得更多“纯洁”,而会得到你想要的效果。如果你想要的话,你可能可以通过一些技巧来确保至少有一个Eval()函数可以返回true,但这可能是黑魔法。 – 2010-10-21 04:55:43

回答

2

这是一个迹象表明,当实现接口的类不需要全部的方法时,你的接口设计可能需要重构。也许你可以把这个接口分成3个接口。

另一种可能性是从中创建一个包装接口,它为不需要的2个方法返回默认值。但在这种情况下,您最终还会得到3个接口(以及原始父接口 - > 4个接口总数)。如果您无法更改原始界面,则此解决方案可以接受。

+0

是的,我可以声明一个'template class MyFunction'并使用三种特化。但问题是我必须创建对象从一个工厂的所有三种类型和一个集合中的商店。或者我可能会放弃它。 – nakiya 2010-10-21 05:31:53

+1

然后,我宁愿第一个(实现类中的方法,返回false)。在我看来,不需要实现方法的接口并不是一个接口。 – MOnsDaR 2010-10-21 05:46:46

3

由于Eval()中使用的类型与实现数量之间存在一对一的映射关系,所以模板成员函数应该可以工作。

class MyFunction { 

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

然后为不应该返回false的类型实现特化。

这只需要单个泛型实现来返回false,并且在任何情况下都需要三个实现。

+0

+1很好的答案。但是,'MyFunction'的实现将驻留在一个共享对象中。这是否会导致问题? – nakiya 2010-10-21 06:17:53

+0

如果实现需要访问相同的成员变量(例如保存状态),那么这可能是一个问题。否则,它应该没问题。 – 2010-10-21 06:31:13

+0

对我不太清楚。你能解释一下吗? – nakiya 2010-10-21 06:38:18

0

我认为你可能会更好地声明一个单一的纯虚拟方法来覆盖,但它会返回一个区分的联合体或variant /任何类型的第一个参数。然后每个派生类可以返回它想要的类型。用你目前的方式,你需要决定调用哪种方法。有了歧视的联盟,你只能调用一种方法,但是在它返回后做出决定如何处理它。

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; 
} 

变成类似:

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; 
} 

显然我已经跳过了错误检查之类的,但它是非常相似,我认为你打算这样做。

相关问题