如何在一个类中正确管理2个不同类型的容器?

时间:2016-12-29 21:07:25

标签: c++

我有以下(有点伪)代码,它处理2个不同(但有些类似)类型的容器,我讨厌添加和删除这些重复(以及我的实际代码中的2个搜索功能)

class PureAbstractClass
{
public:
    virtual char Func() = 0;
}

class PureOpt1 : PureAbstract
{
public:
    virtual int FOption1(A, B, C) = 0; // Notice 'C'
}

class PureOpt2 : PureAbstract
{
public:
    virtual int FOption2(A, B, D) = 0; // Notice 'D'
}

class Handler
{
public:
    void Add(PureOpt1* arg) { v1.add(arg); }
    void Add(PureOpt2* arg) { v2.add(arg); }

    // This is implemented using lambda
    // Sorry for LINQ syntax, lambdas are too long for pseudo code
    void Del1(char c) { arg = v1.find(obj => obj->Func() == c); v1.del(arg); }
    void Del2(char c) { arg = v2.find(obj => obj->Func() == c); v2.del(arg); }

    void Process(ch, A, B, C, D)
    {
        o1 = v1.Find(obj => obj->Func() == ch);

        if( null == o1 )
        {
             o2 = v2.Find(obj => obj->Func() == ch);
             if( null == o2 )
             {
                  DoSomething();
             }
             else
             {
                  o2->FOption2(A, B, D);
             }
        }
        else
        {
             o1->FOption1(A, B, C);
        }

    }

private:
    vector<PureOpt1*> v1;
    vector<PureOpt2*> v2;
}

由于Handler而无法将Process()作为模板类。

有没有更正确的方法来实现这种代码?

2 个答案:

答案 0 :(得分:3)

  

如何在班级中正确管理2个不同类型的容器?

答案仅使用1个容器。

最简单的解决方案是在基类中使用纯粹的虚拟方法:

class PureAbstractClass
{
public:
    virtual char Func() = 0;
    virtual int FOption(A, B, C, D) = 0; 
}

然后两个孩子都覆盖FOption()并忽略他们不需要的参数。可能有更好的解决方案,但您没有提供足够的信息。你的解决方案 - 将它们放在两个独立的容器中可能是最糟糕的。正如您所看到的solution与继承冲突一样(您删除了继承并使两个子项成为独立类,并且代码中不会发生任何变化)。或者,您可以使用dynamic_cast,但使用它通常会显示错误的程序设计:

PureAbstractClass *o = find( ... );
if( !o ) {
   DoSomething();
   return;
}
if( PureOpt1 *po1 = dynamic_cast<PureOpt1 *>( o ) )
     po1->FOption1( A, B, C );
else {
    if( PureOpt2 *po2 = dynamic_cast<PureOpt2 *>( o ) )
        po2->FOption2( A, B, D );
    else
       // something wrong object is not PureOpt1 nor PureOpt2
}

注意:在这种情况下,FOption1()FOption2()完全没有必要是虚拟的。你不应该忘记将虚拟析构函数添加到基类。

或者你可以使用boost::variant和访问者模式,在这种情况下你也不需要继承,但你可以使你的代码通用。

答案 1 :(得分:0)

如果可能,FOption1 / 2为int Func(数据常量和数据)。然后,您创建数据并将其传递给它。数据可以包含四个不同的信息,C和D是可选的。然后,Func的具体实现可以根据需要处理该数据