【问题标题】:How to merge two classes with much the same code but operating on different structures如何合并两个具有相同代码但在不同结构上运行的类
【发布时间】:2013-08-15 18:33:38
【问题描述】:

我正在尝试通过删除重复代码来改进现有的 C++ 代码,但无法提出令人信服的方法。非常感谢更有经验的 C++ 同事提供的任何见解。

所以我有两个我无法控制的结构定义:

struct struct_1
{
...
other_s * s1;
other_s * s2;
other_s * s3;
... //other fields
};

struct struct_2
{
...
other_s * s1;
other_s * s2;
other_s * s3;
... //other fields, different than struct_1, but not that important
};

最后是我要改进的代码。我有两个几乎相同的类,它们在同名的结构字段上以相同的方式操作,但这些字段来自不同的结构。这些类不对仅存在于一个结构中的结构字段进行操作。在这里(简化):

class class_1
{
    struct_1 * s;

    class_1(){
        s = new struct_1(); //the only practical difference
        ...
    }

    void method()
    {
        ...

        //this is simplification, in reality the code is more complex
        //however the same as in class_2
        inner_data += s->s1;
        inner_data += s->s2;
        inner_data += s->s3; 
        ...
    }
    //other methods
};

class class_2
{
    struct_2 * s;

    class_2(){
        s = new struct_2(); //the only practical difference
        ...
    }

    void method()
    {
        ...

        //this is simplification, in reality the code is more complex
        //however the same as in class_1
        inner_data += s->s1;
        inner_data += s->s2;
        inner_data += s->s3; 
        ...
    }
    //other methods
};

我花了一些时间尝试对其进行返工,但最终无济于事。我的方法是只使用一个类 class_1,但我无法避免在没有多个 if 分散的情况下访问 struct_1 和 struct_2 的问题。 感谢您的帮助!

【问题讨论】:

    标签: c++ design-patterns refactoring code-duplication


    【解决方案1】:

    C++ 有一个模板:

    template<typename T>
    class MyClass
    {
        T* s;
    
        MyClass(){
            s = new T(); //the only practical difference
            ...
        }
    
        void method()
        {
            ...
    
            //this is simplification, in reality the code is more complex
            //however the same as in class_2
            inner_data += s->s1;
            inner_data += s->s2;
            inner_data += s->s3; 
            ...
        }
        //other methods
    };
    

    现在您可以将您的课程用作:

    MyClass<struct_1> a;
    

    MyClass<struct_2> b;
    

    编译器会根据你的模板为这些类生成定义。

    不要忘记在析构函数中释放内存!

    【讨论】:

    • 谢谢!像魅力一样工作。
    【解决方案2】:

    您正在寻找模板:

    template <typename S>
    class C {
        S * s;
    
        C() s(new S()) {}
    
        void method() {
            // This is all fine as long as `S` has these members
            inner_data += s->s1;
            inner_data += s->s2;
            inner_data += s->s3;
        }
    };
    

    那么你的课程可以是这方面的专业化:

    typedef C<struct_1> class_1;
    typedef C<struct_2> class_2;
    

    (并且,希望您的真实代码遵循Rule of Three,因为它与低级内存分配有关。)

    【讨论】:

      【解决方案3】:

      模板可以解决这个问题,但如果结构大多相同(例如,如果 struct_2 只是向 struct_1 添加更多字段),您可以将 struct_1 转换为基类,将 struct_2 转换为从它派生的类(仅添加新的数据成员)。

      或者,您也可以将所有数据成员合并到 struct_1 中(再次假设数据成员与 struct_s 基本相同,只是添加了一些)并添加一个标志或类型来指示哪些成员是有效的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-31
        • 2022-01-22
        • 1970-01-01
        相关资源
        最近更新 更多