【问题标题】: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 的一些功能。

【问题讨论】:

    标签: c++ 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 指针并且不能访问失败类型的成员。
    猜你喜欢
    • 1970-01-01
    • 2017-10-01
    • 2022-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-07
    相关资源
    最近更新 更多