如何避免代码重复或多次迭代?

时间:2011-09-16 01:53:06

标签: c++ oop code-reuse

考虑下面给出的代码:

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:我可以编写两个类,MyfuncMyfuncSSN派生自Myfunc,并具有虚函数process()。但是,打印数字女性的代码段必须从process()类的Myfunc方法复制到MyfuncSSN类。这里没有代码重用。

什么是更好的解决方案?

2 个答案:

答案 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”。