以不同方式处理子类/避免代码重复

Posted

技术标签:

【中文标题】以不同方式处理子类/避免代码重复【英文标题】:Treating a subclass differently / avoiding code-duplication 【发布时间】:2014-05-10 22:08:12 【问题描述】:

我想知道如何在下面给出的场景中避免代码重复。

(有个问题:How do I check if an object's type is a particular subclass in C++? 答案是这是不可能的,我猜即使使用动态演员表成员访问也是不可能的。)

所以我想知道您如何避免在不同的方法中使用几乎相同的代码,而只有一种方法会有一些额外的操作。

class Basic 
    ...


class Advanced : public Basic 
    ...



AnotherClass::lengthy_method(Basic *basic) 
    // do a lot of processing, access members of basic

    if (*basic is actually of class Advanced)
        // do one or a few specific things with members of Advanced

    // more processing just using Basic

    if (*basic is actually of class Advanced)
        // do one or a few specific things with members of Advanced

    // more processing just using Basic

同样从设计的角度来看,AnotherClass::lengthy_method 不想在BasicAdvanced 中定义,因为它并不真正属于它们中的任何一个。它只是在他们的同类上运作。

我很好奇语言专家知道什么,我希望有一个不错的解决方案,至少可以通过 C++11 的一些功能。

【问题讨论】:

【参考方案1】:

这里可以使用dynamic_cast,只要将要访问的Advanced成员声明为public,或者AnotherClass声明为Advancedfriend即可:

AnotherClass::lengthy_method(Basic *basic) 
    // do a lot of processing, access members of basic

    Advanced *adv = dynamic_cast<Advanced*>(basic);
    if (adv != NULL) 
        // use adv as needed...
    

    // more processing just using Basic

    if (adv != NULL) 
        // use adv as needed...
    

    // more processing just using Basic

另一种选择是使用多态性而不是 RTTI。在Basic 中公开一些额外的虚方法,它们什么都不做,然后让Advanced 覆盖它们:

class Basic 
    ...
    virtual void doSomething1() 
    virtual void doSomething2() 


class Advanced : public Basic 
    ...
    virtual void doSomething1();
    virtual void doSomething2();


void Advanced::doSomething1() 
    ...


void Advanced::doSomething2() 
    ...
    

AnotherClass::lengthy_method(Basic *basic) 
    // do a lot of processing, access members of basic

    // do one or a few specific things with members of Advanced
    basic->doSomething1();

    // more processing just using Basic

    // do one or a few specific things with members of Advanced
    basic->doSomething2();

    // more processing just using Basic

【讨论】:

谢谢!很高兴知道Advanced的成员访问实际上是可以的。 你为什么认为这是不可能的? 令我惊讶的是,编译器允许访问可能不存在的成员。 不会的。你不能 dynamic_cast 一个指向另一个 unrelated 类型的对象指针。如果转换成功,则您有一个有效的指针,并且可以访问您转换为的类型的成员。如果转换失败,你有一个 NULL 指针并且不能访问失败类型的成员。

以上是关于以不同方式处理子类/避免代码重复的主要内容,如果未能解决你的问题,请参考以下文章

子类化 Flask 可插拔视图以实现可扩展功能的最佳方式

通过SQL脚本导入数据到不同数据库避免重复导入三种方式

避免在复制构造函数和 operator= 中重复相同的代码

C++预处理器:避免成员变量列表的代码重复

[设计模式]模板模式

重构手法之处理概括关系