0

除了修改所有派生类之外,我无法找到解决问题的方法。

我有一个Base类和大约 1000 个Derived类继承自Base. 现在,还有另一个类说它Container包含一个Base类指针向量std::vector<Base *> derivList

上面的列表填充了创建后所有派生类对象的地址。

所有文件都在不同的翻译单元中。

我想做什么

1)能够使用容器中指向不同派生类的向量元素Base从类中调用类的单个函数。Container

2)但是当我调用这个函数时,在那个函数内部我应该能够访问类指针指向public members的不同Derived类。Base

class Base
{
  public: 
    virtual void someMethod();
    void containerCallsThisMethod();
};
void Base::containerCallsThisMethod()
{
  // I need to access the public functions of derived classes here
  // say: Derived1::calc(), Derived2::calc,.( I don't have derived class names here in  Base)
}

class Derived1:public Base
{
   public:
      void calc();
};

class Container
{
    std::vector<Base *> derivList;
    void execute();
};

void Container::execute()
{
    for(i = 0; i < derivList.size();i++)
    {
      derivList[i]->containerCallsThisMethod();
    }
}

我的限制是

  • 我不应该班级,Derived因为它很费力,但我仍然可以改变Base班级。
  • Base不能有一个Derived类的列表(甚至没有前向声明)。

我想我可以通过this指针来做到这一点,因为它具有函数的ClassName类型non-const并且它指向派生类对象。但我无法Derived使用this.

有没有什么方法可以在不费力、任何特定设计模式或黑客攻击的情况下做到这一点?

4

3 回答 3

0

如果

不同派生类的公共成员

您需要访问的是具有相同签名的方法,但在每个派生类中实现方式不同(您的示例似乎表明了这一点)您只是发现自己处于虚拟方法绑定的最基本用例中。

然后你会很幸运:你只需要在类定义中的方法签名之前添加 virtual 关键字。

class Base
{
    void containerCallsThisMethod()
    {
         calcDerivedMethod();
    }

    virtual void calcDerivedMethod();
}

class DerivedA : public Base
{
    void calcDerivedMethod()
    {
       //Specific implementation for DerivedA class.
    }
}

这里发生的事情正是您所描述的要求:容器方法execute()在它指向的每个对象上依次调用containerCallsThisMethod() 。这个调用最终总是Base::containerCallsThisMethod()。但是在最后一个方法中,对calcDerivedMethod()的调用被分派给指针的动态类型(即 Derived 类)。您只需在Base中的calcDerivedMethod()声明前添加virtual关键字即可获得此动态调度。

于 2013-08-07T11:19:47.720 回答
0

如果您有一个带有派生类的基类,则这些派生类会覆盖该函数,让我们调用它func(),然后func()将调用该覆盖。据我所知,您想要的唯一解决方案是依靠派生类的良好行为或将func()其作为静态函数,将其放入朋友类,或将其放入静态内部类。

于 2013-08-07T11:15:00.117 回答
0

If I understand you correctly, you can just declare calc as a (possibly protected) virtual function in Base. This only works if calc has exactly the same signature in all derived classes. In that case, no code must be changed in the derived classes. Now, when you call this->calc in Base it will be dispatched to the implementation in Derived.

class Base
{
  public: 
    vitrual void someMethod();
    void containerCallsThisMethod();

    virtual ~Base(); // Important !!
  protected:
    virtual void calc() = 0;
};
void Base::containerCallsThisMethod()
{
  calc(); // will call derived class implementation
}

Remember to add a virtual destructor to Base when you do this.

This works because when a method is declared virtual, it will be virtual in all derived classes as well, even if not explicitly specified so.

于 2013-08-07T11:17:02.217 回答