【问题标题】:2 C++ classes with same functionality but different variable names - which pattern to use?2 个具有相同功能但变量名不同的 C++ 类 - 使用哪种模式?
【发布时间】:2021-07-01 07:40:18
【问题描述】:

我有 2 个 C++ 类,它们具有相同的变量类型,并且需要对这些变量执行完全相同的操作。但是,这两个类的变量名和函数名是不同的,因为它们在各自的类中含义不同。

如何在不重复代码的情况下实现这一目标?继承或模板在这里有帮助吗?

这是一个精简的例子。

class A
{
    private:
       float m;
       float n;

    public:
       float foo() {return m + n};
};

class B
{
    private:
       float p;
       float q;

    public:
       float bar() {return p + q};
};

在我的例子中,操作和变量比上面的玩具例子更复杂。两个类之间的唯一区别是变量和函数名称。其余的都是一样的。如何在 C++ 中重构它?

【问题讨论】:

  • 好吧,你应该自己知道为什么它们首先是分开的。为什么不在两种情况下都使用一个类? (我认为大多数其他解决方案可能会增加不必要的复杂性)
  • 如何在不重复代码的情况下实现这一点? -- 代码重复没有问题。如果类型意味着不同的东西,那么类具有相同的布局只是巧合。如果我的有 20 名成员的班级被称为 Car,而另一个偶然有相同 20 名成员的班级,但它是 Toaster?顺便说一句,如果您查看一个真实世界的程序,该程序可以有许多“两个成员”类,它们都意味着不同的东西。
  • 如果我们知道这些类是什么会很有帮助。
  • 使用std::pair<float,float> 作为泛化(resp class Base<T> { std::pair<T,T> y; public: T baz() { return y.first + y.second; }};)怎么样?
  • 只是为了呼应@PaulMcKenzie,如果它们用于表示不同的事物并用于不同的情况,那么具有相同布局的两种不同类型是没有问题的。如果你真的只想拥有一种类型(假设它叫做MySingleType),你可以使用typedef MySingleType NameOne;typedef MySingleType NameTwo; 来创建别名,那么你可以使用NameOneNameTwo,就好像它们是他们自己的一样类型。

标签: c++ oop templates inheritance design-patterns


【解决方案1】:

有几种方法可以解决这个问题。

  1. 只使用一个类。如果功能相同而您只是更改名称,那么为什么需要多个类。
    • 优点:尽量减少代码重复
    • 缺点:如果这些是针对两个不同的应用程序,则您违反了单一责任原则
  2. 创建一个包含所有函数的基类,然后为每个案例创建一个具有正确名称的基类。
    • 优点:尽量减少代码重复
    • 缺点:除了偶然性之外,可能没有关系
  3. 创建一个类,typedef 创建另一个名称。
    • 优点:尽量减少代码重复
    • 缺点:只更改了“类”的名称,没有更改方法调用
  4. 将其保留为两个类
    • 优点:每个类负责自己不相关的操作,并且独立于其他类进行操作
    • 缺点:可能的代码重复

一般来说,在不知道类的细节的情况下,我会说最好的方法是让两个类都保持原样。如果他们在做不同的事情,并且碰巧两者有相似的方法,那是机会,不值得牺牲可读性和单一责任原则。
如果它们是相关的,那么考虑它是否会遵循继承关系。如果不是,再次将它们保留为两个类。

【讨论】:

    【解决方案2】:

    除了使用了哪些变量之外,两个相当复杂的函数是相同的?听起来像是一个简单的案例,可以将共性提取到一个单独的函数中,该函数为不同的事物提供参数。例如:

    float DoComplicatedThing(float a, float b)
    {
        // whatever the complicated thing is
        // ...
    
        // but staying with your example it's just:
        return a + b;
    }
    
    class A
    {
        private:
           float m;
           float n;
    
        public:
           float foo() { return DoComplicatedThing(m, n) };
    };
    
    class B
    {
        private:
           float p;
           float q;
    
        public:
           float bar() { return DoComplicatedThing(p, q) };
    };
    

    如果有充分的理由让AB 从公共基类派生,那么DoComplicatedThing 可能是来自该基类的静态函数。否则它可能只是一个没有类的独立函数(如我的示例)。

    【讨论】:

      猜你喜欢
      • 2011-10-18
      • 2011-05-18
      • 2022-01-11
      • 1970-01-01
      • 2020-12-09
      • 2012-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多