我有三个类,每个类都存储自己的double值数组。为了填充数组,我使用一个相当复杂的函数,比如说foo()
,它接受几个参数并计算数组的适当值。
我的三个类中的每一个都使用相同的功能,只进行了微小的调整(即输入参数略有不同)。每个类实际上非常相似,尽管它们在检索数组的值时都执行单独的逻辑。
所以我想知道如何“共享”该函数以便所有类都可以使用它,而不必复制代码?
我在考虑创建一个包含函数foo()
和虚拟get()
方法的基类。然后我的三个类可以继承这个基类。或者,我也想也许还有一个全球性的功能?可能将函数放入命名空间?
答案 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所说的那样解析不同的格式,那么传入一个解析器对象(这将是多态的)会更好,因为它可以让您更轻松地模拟事物,但是您还没有给出足够的细节可以肯定地说。