在类之间共享功能

时间:2012-01-08 23:54:56

标签: c++ oop

我有三个类,每个类都存储自己的double值数组。为了填充数组,我使用一个相当复杂的函数,比如说foo(),它接受​​几个参数并计算数组的适当值。

我的三个类中的每一个都使用相同的功能,只进行了微小的调整(即输入参数略有不同)。每个类实际上非常相似,尽管它们在检索数组的值时都执行单独的逻辑。

所以我想知道如何“共享”该函数以便所有类都可以使用它,而不必复制代码?

我在考虑创建一个包含函数foo()和虚拟get()方法的基类。然后我的三个类可以继承这个基类。或者,我也想也许还有一个全球性的功能?可能将函数放入命名空间?

6 个答案:

答案 0 :(得分:3)

如果这个类除了这个foo()函数之外没有任何共同之处,那么将它放在基类中是愚蠢的。让它成为一个免费的功能。 C ++不是Java。

答案 1 :(得分:0)

如果类的基础数据相同(双精度数组),考虑使用单个类并重载构造函数,或者只使用3个不同的函数:

  

void PopulateFromString(const string&)
  void PopulateFromXml(...)
  void PopulateFromInteger(...)

如果每个类类型的数据或行为不同,那么您的基类解决方案就很好。

如果与特定类行为(多态)无关,您还可以在与作为实用函数的类相同的命名空间中定义函数。 Bjarne StroupStroup推荐这种方法。

答案 2 :(得分:0)

在基类中声明函数听起来是最合适的解决方案。不确定你是否需要虚拟“get”,而只是在基类中声明数组并为后代提供访问方法。

更复杂的部分是“输入参数略有不同”。如果参数只有类型不同,那么您可以编写模板函数。如果差异比唯一的解决方案更重要,我看到将主函数拆分为多个逻辑块,并在后代类中使用这些块来执行最终结果。

答案 3 :(得分:0)

如果您的类非常相似,您可以创建一个模板类,其中包含三个具有函数foo<T>()

的不同实现

答案 4 :(得分:0)

在基类中实现该功能。如果这些类与你说的类似,那么它们应该来自一个基类!如果有几个函数,比如foo(),在某些情况下将它们组合到另一个类中可能是合理的,这个类被/用于你的类。

答案 5 :(得分:0)

为了这个答案,我假设你所拥有的课程在任何其他方面都不常见;他们可能会加载相同的数据,但他们提供不同的接口。

这里有两种可能的情况,你还没告诉我们它是哪一种。它可能更像是

void foo(double* arr, size_t size) {
    // Some specific code (that probably just does some preparation)
    // Lots of generic code
    // ...
    // Some more specific code (cleanup?)
}

或与

类似的东西
void foo(double* arr, size_t size) {
    // generic_code();
    // ...
    // specific_code();
    // generic_code();
    // ...
}

在第一种情况下,通用代码可能很容易被放入一个单独的函数中,然后创建一个基类并没有多大意义:你可能会私下继承它,除非你有充分的理由,否则你应该更喜欢组合而不是私人继承。如果新功能从中受益,您可以将它放在自己的类中,但并不是绝对必要的。是否将其放在命名空间中取决于您如何组织代码。

第二种情况比较棘手,在这种情况下我会建议多态性。但是,您似乎不需要运行时多态性,所以您也可以编译时。使用这是C ++的事实,您可以使用CRTP:

template<typename IMPL>
class MyBase {
    void foo(double* arr, size_t size) {
        // generic code
        // ...
        double importantResult = IMPL::DoALittleWork(/* args */);
        // more generic code
        // ...
    }
};

class Derived : MyBase<Derived> {
    static double DoALittleWork(/* params */) {
        // My specific stuff
        return result;
    }
};

这为您提供了代码组织的优势,并为您节省了一些虚拟功能。另一方面,它确实使得需要实现的功能略微清晰(尽管the error messages are not that bad)。

如果制作一个新功能(可能在一个新课程中)显然会更加丑陋,我只会选择第二条路线。如果您像Andrey所说的那样解析不同的格式,那么传入一个解析器对象(这将是多态的)会更好,因为它可以让您更轻松地模拟事物,但是您还没有给出足够的细节可以肯定地说。