避免公共类中的代码重复

Posted

技术标签:

【中文标题】避免公共类中的代码重复【英文标题】:Avoiding duplication of code in common classes 【发布时间】:2012-03-13 18:44:44 【问题描述】:

我有一个回调函数,叫做

MyCallBack(int type)

我有 3 个类 B、C 和 D 从 A 派生,具有通用方法名称 目前我的代码是这样的

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();

【问题讨论】:

【参考方案1】:

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

你所有的类B,C,D都应该派生自一个抽象类说SuperBase和一个纯虚方法perform()。 您的代码应仅使用指向 SuperBase 的指针,其中包含实际具体类对象的地址。 一旦你有了这个,根据被指向对象的实际类型,来自适当类的方法将被调用。

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

【讨论】:

【参考方案2】:

@Als 使用多态的想法是一个很好的想法 (IMO),但它只有在您将输入整数转换为实际类型之后 才真正起作用。一种方法是索引一个指向对象的指针数组:

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

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

编辑:以防万一您不知道,为了使其正常工作,perform 需要是在A 中声明的(可能是纯的)虚函数,并在每个B 中定义, CD。您需要确保函数的整个签名,而不仅仅是名称,在类之间是相同的。

【讨论】:

【参考方案3】:

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();

【讨论】:

不应该是MyCallBack(A&amp; performer)通过一个指针(即MyCallBack(A* performer))然后用performer-&gt;perform()调用它吗? 通过引用基类来引用派生类是合法的。当然,如果传入的是 A*,那么他必须使用 A*。在可能的情况下,人们应该更喜欢对指针的引用。【参考方案4】:

您应该创建对象工厂或只是静态(全局)方法返回指向基类型的指针(或引用,可能),但包含派生类型的对象。

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();

【讨论】:

以上是关于避免公共类中的代码重复的主要内容,如果未能解决你的问题,请参考以下文章

类中的属性与公共声明变量[重复]

继承和多态

模板模式

模板模式

具体类中的受保护构造函数与抽象类中的公共构造函数

同步类中的公共变量