【问题标题】:C++: How to obtain different behaviour for methods of abstract-derived classes from the derived classes of another abstract class?C ++:如何从另一个抽象类的派生类中获得抽象派生类的方法的不同行为?
【发布时间】:2014-11-16 04:39:45
【问题描述】:

我有两个抽象类,fooBase 和 barBase。它们都有两个(或更多)具体的子类(foo1foo2bar1bar2)。我想要barBase 的每个子类的一个方法来调用与fooBase 中的一个具体类对应的方法。例如,

class fooBase{
    virtual int method()=0;
};

class foo1 : public fooBase {
    public :
    foo1(){}
    int method(){return 1;}
};

class foo2 : public fooBase {
    public :
    foo2(){}
    int method(){return 2;}
};

class barBase {
    virtual int drilldown(fooBase &)=0;
};

class bar1 : public barBase {
    public :
    bar1(){}
    int drilldown(foo1 & f){return f.method();}
};

class bar2 : public barBase {
    public :
    bar2(){}
    int drilldown(foo2 & f){return f.method();}
};

然后在 main() 中执行:

    foo1 f1;
    foo2 f2;
    bar1 b1;
    bar2 b2;

但我得到了错误:Variable type 'b1' is an abstract class(同样适用于 b2)。我知道发生这种情况是因为barBase 中的方法drilldown 是使用引用fooBase 抽象类的参数定义的,但bar1 和bar2 正试图深入到具体的子类中,因此编译器不会t 认识到drilldown(fooBase &) 的方法是在子类中定义的。我该如何解决这个问题,以便获得我想要的行为?这种情况下正确的设计模式是什么?


我最终使用了 Joachim Pileborg 的解决方案(见下文)。我还必须将带有参数 barBase & 的任何函数更改为模板函数,即

 template<class T>
 int fn(barBase<T> & b, T & f){
    return b.drilldown(f);
 }


int main(int argc, const char * argv[]) 
{
    foo1 f1;
    foo2 f2;
    bar1 b1;
    bar2 b2;
    std::cout<<b1.drilldown(f1);
    fn(b1,f1);
return 0;
}

【问题讨论】:

  • bars 定义为类模板和实例化,而不是多态层次结构?
  • @Sambuca,是的,我意识到这一点。
  • @OliverCharlesworth,你能给我更多的信息吗?

标签: c++ inheritance polymorphism abstract-class virtual-functions


【解决方案1】:

看来你只需要:

class barBase {
    int drilldown(fooBase &f){ return f.method(); }
};

还有你假设的功能:

int f(barBase & b, fooBase & f){return b.drilldown(f);}

会正常工作的。

【讨论】:

  • 这很好,但我真的需要不同的 bar 子类,它们有其他方法具有不同的实现来区分它们,而不仅仅是通过向下钻取。还是谢谢。
【解决方案2】:

你可以将barBase定义为模板,比如

template<typename T>
struct barBase {
    virtual int drilldown(T &)=0;
};

class bar1 : public barBase<foo1> {
    public :
    bar1(){}
    int drilldown(foo1 & f){return f.method();}
};

class bar2 : public barBase<foo2> {
    public :
    bar2(){}
    int drilldown(foo2 & f){return f.method();}
};

当然,它的缺点是您不能使用指针或对barBase 的引用来引用它的任何一个子类。

【讨论】:

  • 这大大降低了基类的通用性。为什么不去完整的 CRTP?
  • @JoachimPileborg,我希望 barBase 引用子类。例如,如果我有一个函数 int f(barBase & b, fooBase & f){return b.drilldown(f);},我想要行为 f(bar1 b,f)=1 和 f(bar2 b,f )=2.
  • @Deduplicator,您能否提供有关 CRTP 的更多信息?我可以使用它来保持 barBase 类的通用性并仍然引用我在上面的评论中所写的子类吗?
  • “你不能使用 barBase 来引用它的任何一个子类”。这并不是一个真正的缺点。您将无法使用 barBase 做任何有用的事情,除非将其投射回其中一个栏。
  • @JaseUknow 如果b 指的是bar1f 指的是foo2,该怎么办? b.drilldown(f)是什么意思?
猜你喜欢
  • 2011-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-11
  • 2020-09-01
  • 1970-01-01
  • 2015-05-13
  • 1970-01-01
相关资源
最近更新 更多