2012-03-13 55 views
2

我有调用的回调函数作为避免重复的代码中的公共类

MyCallBack(int type) 

和我有3类B,C和d由具有共同的方法得到的命名 目前我的代码是这样

MyCallBack(int type){ 
if(type == 1){ 
B b; 
b.perform(); 
}else if(type==2) { 
C c; 
c.perform(); 
}else if(type ==3){ 
D d; 
d.perform(); 
} 

有没有办法可以减少这种代码类似

MyCallBack(int type){ 
Common object(type); 
object.perform(); 
} 

回答

3

基本上,你需要的是多态性。

所有的类BCD应该从一个抽象类派生说SuperBase用纯虚方法perform()
您的代码应该只使用指向SuperBase的指针,其中包含实际的具体类对象的地址。
一旦你有了这个,取决于被指向的对象的实际类型,将调用适当类的方法。

该方法的优点是没有硬编码类型检查&也使用Open Closed principle松散耦合设计的灵活性。

1

如何关于interface

class A 
{ 
    public: 

     virtual void perform() = 0; 
}; 

class B : public A 
{ 
    public: 

     void perform() { ... } 
}; 

// Same for C, and D 

所以你的回调会再看看这样的:

MyCallBack(A& performer) 
{ 
    performer.perform(); 
} 

如果你不能改变回调的签名,又有怎样的abstract factory pattern

function A* AFactory(int type) 
{ 
    switch(type) 
    { 
     case 1: return new B(); // Assuming B, C, D all derive from A 
     case 2: return new C(); 
     case 3: return new D(); 
     default: return nullptr; // nullptr is a c++11 thing. Use NULL, if you're still on C++03 
    } 
} 

,然后回调...

MyCallBack(int type) 
{ 
    std::unique_ptr<A> obj(AFactory(type)); // this will automatically release the memory once it falls out of scope 
    obj->perform(); 
} 
+0

不应该通过指针(即MyCallBack(A * performer))指向'MyCallBack(A&performer)',然后用'performer-> perform()'调用它? – 2012-03-13 18:56:43

+0

通过引用基类来引用派生类是合法的。当然,如果一个A *被传入,那么A *就是他必须使用的。在可能的情况下,应该更喜欢引用指针。 – luke 2012-03-13 19:01:10

-1

您应该创建Object Factory或静态(全局)方法返回指针(或引用,也许)到基类型,但包含派生类型的对象。

CBase* CreateObjectBasedOnType(int type) 
{ 
    // check for type and return appriopriate derived object 
} 

MyCallBack(int type) 
{ 
    CreateObjectBasedOnType(type)->perform(); 
} 

请注意,您要调用的方法应该是虚拟的。

更好的方法可以使用模板

template<typename T> 
MyCallBack() 
{ 
    T Obj; 
    Obj.perform(); 
} 
2

@Als'使用多态的想法是一个很好的(IMO),但只有真正的作品后,你从输入整数转换成实际类型。要做到这一点的方法之一将是索引指针数组对象:

MyCallback(int type) { 
    static A *ptrs[] = { new B, new C, new D}; 

    ptrs[type-1]->perform(); 
} 

编辑:万一你不知道,这才能正常工作,perform需要一个虚函数声明(大概是纯的)在A中虚拟,并在B,CD中的每一个中定义。您需要确保函数的整个签名(不仅仅是名称)在类之间是相同的。