C++ C++;,抽象类与继承

C++ C++;,抽象类与继承,c++,inheritance,abstract,C++,Inheritance,Abstract,我正在尝试一个接一个地处理类实例。 我有一个包含doStuff方法的抽象基类(这里是IBase)。 此方法将在扩展类中重写,以便处理所有其他定义的类 这是我正在建造的图书馆的一部分。我希望库用户编写基本对象。每个基类都需要通过doStuff方法与另一个基类对象交互。需要容器来处理多个基本对象 这不是我第一次遇到这个问题,但我不记得上次是怎么遇到的。这种类可以用于很多事情。这里,它是一个碰撞检测系统。IBase表示一个抽象的HitBox,容器表示发生碰撞的场景。在这种情况下,Container::

我正在尝试一个接一个地处理类实例。 我有一个包含doStuff方法的抽象基类(这里是IBase)。 此方法将在扩展类中重写,以便处理所有其他定义的类

这是我正在建造的图书馆的一部分。我希望库用户编写基本对象。每个基类都需要通过doStuff方法与另一个基类对象交互。需要容器来处理多个基本对象

这不是我第一次遇到这个问题,但我不记得上次是怎么遇到的。这种类可以用于很多事情。这里,它是一个碰撞检测系统。IBase表示一个抽象的HitBox,容器表示发生碰撞的场景。在这种情况下,Container::process检查命中框之间的转换,Container::process用于实现优化算法(四叉树,…)

我是这样构建这些类的:

class IBase {
    public:
        virtual void doStuff(IBase* base) = 0;
}

class Base {
    public:
        virtual void doStuff(Base* base) {
            foobar();
        }
        virtual void doStuff(IBase* base) {
            // irrelevant
        }
}

class Container {
    public:
        void process() {
            for (std::list<IBase*>::iterator it=base_list.begin() ; it!=base_list.end() ; it++) {
                for (std::list<IBase*>::itarator jt=std::next(it) ; jt!=base_list.end() ; jt++) {
                    (*it)->doStuff(*jt);
                }
            }
        }
    private:
        std::list<Ibase*> base_list;
}
class-IBase{
公众:
虚拟空穴密度(IBase*base)=0;
}
阶级基础{
公众:
虚虚空doStuff(基*基){
foobar();
}
虚拟虚空doStuff(IBase*基础){
//无关的
}
}
类容器{
公众:
无效过程(){
for(std::list::iterator it=base_list.begin();it!=base_list.end();it++){
for(std::list::itarator jt=std::next(it);jt!=base_list.end();jt++){
(*it)->doStuff(*jt);
}
}
}
私人:
标准::列表基本列表;
}
但是在循环中,当使用两个基本对象时,我无法访问void Base::doStuff(Base*)。 我只能调用Base::doStuff(IBase*),这不是我想要的

这件有什么帮助吗?我理解这个问题,但我看不出解决办法。这是处理它的好方法还是我需要重新考虑我的架构?你会怎么做?我认为对于这样一个问题,必须存在一种设计模式,但我没有找到任何适合的模式


谢谢

C++不支持参数的逆变。另见


doStuff(IBase*Base)
主体中显式调用
doStuff(Base*Base)
可能会更好。

C++不支持参数的逆变。另见


doStuff(IBase*Base)
主体中显式调用
doStuff(Base*Base)
可能会更好。

当从
*it
*jt
解除引用时,对象被引用为
IBase
对象,而不是基本对象。这意味着只能调用
IBase
中的方法

您的虚拟方法:

virtual void doStuff(Base* base) { ... }
没有凌驾于任何事情之上。它正在创建一个新的虚拟方法,只能从底部向下访问。当您从
IBase
指针调用
doStuff
时,它将调用:

virtual void doStuff(IBase* base) { ... }
它与
IBase
中定义的签名相匹配

如果你想执行你的
foobar
函数,你应该在
base
上做一些检查,当它基于覆盖
doStuff
时,一旦你确定它是安全的,就把它转换成
base*
,然后根据需要使用它

virtual void doStuff(IBase* base) {
  // not irrelevant
  if (base->isBase()) 
  {
    foobar();
  }
}

最后,如前所述,将
doStuff
公开。

当从
*it
*jt
取消引用时,您的对象被引用为
IBase
对象,而不是基本对象。这意味着只能调用
IBase
中的方法

您的虚拟方法:

virtual void doStuff(Base* base) { ... }
没有凌驾于任何事情之上。它正在创建一个新的虚拟方法,只能从底部向下访问。当您从
IBase
指针调用
doStuff
时,它将调用:

virtual void doStuff(IBase* base) { ... }
它与
IBase
中定义的签名相匹配

如果你想执行你的
foobar
函数,你应该在
base
上做一些检查,当它基于覆盖
doStuff
时,一旦你确定它是安全的,就把它转换成
base*
,然后根据需要使用它

virtual void doStuff(IBase* base) {
  // not irrelevant
  if (base->isBase()) 
  {
    foobar();
  }
}

最后,如前所述,将
doStuff
公开。

我在
process()
中没有看到任何基本对象。我遗漏了什么吗?似乎您正在尝试创建一个容器,其中包含一个Base*对象列表(或指向从IBase派生的对象的指针),对吗?然后迭代列表并调用多态doStuff?您应该能够做到这一点,只需将您的虚拟doStuff()声明为public(或使容器成为IBase的朋友)我就闻到了一种气味。你到底想做什么?看起来像你真正想要的,有时实现为。我在
process()
中没有看到任何基本对象。我遗漏了什么吗?似乎您正在尝试创建一个容器,其中包含一个Base*对象列表(或指向从IBase派生的对象的指针),对吗?然后迭代列表并调用多态doStuff?您应该能够做到这一点,只需将您的虚拟doStuff()声明为public(或使容器成为IBase的朋友)我就闻到了一种气味。你到底想做什么?看起来你真的想要,有时实现为。这个。另外,将doStuff()公开。另外,将doStuff()公开。