考虑下面给出的代码:
struct Person{
enum sex{male,female};
int salary;
};
struct PersonSSN:public Person{
int ssn;
};
我有一个容器,它只包含Person或PersonSSN(在编译时已知),按工资值的升序排序。我必须写一个函数myfunc(),它执行以下操作。
void myfunc(){
if the container contains Person:
print the number of females between two consecutive males.
else if the container contains PersonSSN:
print the number of females between two consecutive males
and
the ssn of the males.
}
我有两个解决这个问题的方法但都有一些缺点。
解决方案1:如果我编写一个函数来打印男性之间的女性数量和打印ssn的另一个函数,我必须重复两次数据,这是非常昂贵的。
解决方案2:我可以编写两个类,Myfunc
和MyfuncSSN
派生自Myfunc
,并具有虚函数process()
。但是,打印数字女性的代码段必须从process()
类的Myfunc
方法复制到MyfuncSSN
类。这里没有代码重用。
什么是更好的解决方案?
答案 0 :(得分:1)
如果您在编译时谈论对象识别,那么答案可能只有一个 - 模板。根据您使用的容器类型,它会有所不同,但如果您使用std :: list,那么它将是
#include <list>
template <typename T>
void myfunc(std::list<T>);
template <>
void myfunc(std::list<Person> lst){
print the number of females between two consecutive males.
}
template <>
void myfunc(std::list<PersonSSN> lst){
print the number of females between two consecutive males
and
the ssn of the males.
}
编辑:
如果你想省略双重迭代,我唯一想象的就是使用signgle模板函数来迭代和打印两个连续男性之间的女性数量,为ssn打印调用另一个模板化函数:
#include <list>
template <typename T>
void printperson(T p){}
template <>
void printperson(Person p){
// Do nothing - perhaps you might skip it and use generic implementation instead
}
template <>
void printperson(PersonSSN p){
print ssn of the person p if it is male.
}
template <typename T>
void myfunc(std::list<T>){
print the number of females between two consecutive males.
and while doing so call printperson(list_element);
}
这可能适用于这个简单的例子,但我相信对于更复杂的例子 - 比如说你想在PersonSSN上打印女性之间的男性数量 - 它可能会变短,因为这两个操作(虽然类似)可能会转向不可能与不同类型的功能分开。然后它需要代码加倍或双重迭代 - 不要认为它有解决方法。
注意:你可能(如评论中所建议的)在function-args中切换到const-references - 我更习惯于使用implicite共享的qt-containers,因此不需要它。
答案 1 :(得分:0)
这个例子在很多不同的层面都是错误的:)
理想情况下,“人”将是一个类; “name”,“sex”和“SSN”都是基类的成员,“process()”可以是method()或虚方法()。
问:是否有可能将Person和PersonSSN更改为类,并将“process()”改为方法?
问:你的程序如何“知道”它是否有“人”记录或“人员记录”记录?你能把这个参数变成你的“process()”函数吗?
ADDENDUM 9.16.2011 :
百万美元的问题是“你的代码如何区分'人'和'人SSN'?”
如果你使用一个类,你可以使用“typeof”(不满意),或者你可以将类特定的行为绑定到类方法(首选,以及“模板”建议的建议)。
你还需要至少三个不同的类:“Person”类(看起来和行为像一个人),“PersonSSN”类(它有额外的数据和可能的额外行为)......和一个“ueber” -class“知道如何COUNT人和PersonSSN的。
所以是的,我建议应该有一些 HAS ,或使用“Persons”和“PersonSSNs”。
是的,你可以将你的代码分解为一个类使用“Process-count-consecutive”,另一个类调用父“Process-count-consecutive”,并添加一个新的“print ssn”。