如何在派生类构造函数之后强制调用基类函数?

时间:2010-04-08 14:17:53

标签: c++ inheritance constructor

我正在为以下情况寻找一个干净的C ++习语:

class SomeLibraryClass {
  public:
    SomeLibraryClass() { /* start initialization */ }
    void addFoo() { /* we are a collection of foos */ }
    void funcToCallAfterAllAddFoos() { /* Making sure this is called is the issue */ }
};
class SomeUserClass : public SomeLibraryClass {
  public:
    SomeUserClass() {
      addFoo();
      addFoo();
      addFoo(); // SomeUserClass has three foos.
    }
};
class SomeUserDerrivedClass : public SomeUserClass {
  public:
    SomeUserDerrivedClass() {
      addFoo(); // This one has four foos.
    }
};

所以,我真正想要的是SomeLibraryClass在构造过程结束时强制执行funcToCallAfterAllAddFoos的调用。用户不能将它放在SomeUserClass :: SomeUserClass()的末尾,这会弄乱SomeUserDerrivedClass。如果他把它放在SomeUserDerrivedClass的末尾,那么它永远不会被SomeUserClass调用。

为了进一步阐明我的需要,想象一下/ * start initialization * /获取一个锁,并且funcToCallAfterAllAddFoos()释放一个锁。

编译器知道对象的所有初始化何时完成,但是我可以通过一些不错的技巧获取该信息吗?

5 个答案:

答案 0 :(得分:9)

我可能会用某种工厂来实现它。以下代码应该被读作伪代码,我还没有尝试编译它或任何东西。

class LibraryClass
{
public:
   template<typename D>
   static D *GetNewInstance()
   {
      // by assigning the new D to a LibraryClass pointer, you guarantee it derives from LibraryClass at compile time
      // that way, the user can't accidentally type "LibraryClass::GetNewInstance<int>()" and have it work
      LibraryClass *c = new D();
      c->funcToCallAfterAllAddFoos();
      return c;
   }

   ...
};

答案 1 :(得分:5)

我不确定这是可能的。但是,你可以稍微重新设计一下:给你的基类构造函数一个参数std::vector<Foo> const &foosToBeAdded,让派生类传递正确的foo

class SomeLibraryClass {
  public:
    SomeLibraryClass(std::vector<Foo> const &foosToBeAdded) {
      /* start initialization */
      std::for_each(foosToBeAdded.begin(), foosToBeAdded.end(),
                    std::bind1st(std::mem_fun(&SomeLibraryClass::addFoo), this));
      funcToCallAfterAllAddFoos();
    }
  private:
    void addFoo(Foo const &someFoo) { /* we are a collection of foos */ }
    void funcToCallAfterAllAddFoos() { /* this is now called at the right time */ }
};

class SomeUserClass : public SomeLibraryClass {
  public:
    SomeUserClass() :
      SomeLibraryClass(makeAFooVector())
    {
    }
  private:
    std::vector<Foo> makeAFooVector() { /* return a vector with three Foos */ }
};

通过让SomeUserClass构造函数也收到vector Foo s,可以扩展模式。然后,在调用基类构造函数之前,它会将自己的Foo添加到列表中。

您也可以传递迭代器而不是vector s。留下来作为练习。

答案 2 :(得分:0)

试试Non-virtual Interface Idiom。使您的公共方法非虚拟,但让它调用私有虚方法。派生类重写此私有虚方法(是的,派生类可以覆盖私有虚拟)。将锁定内容放在公共非虚方法中,围绕私有虚方法的调用。

编辑: 在仔细查看代码之后,我认为你可能最好在基类中使用一个构造函数来接受一个Foo对象的容器并添加它们。

答案 3 :(得分:0)

由于C ++不允许反射,不能,您无法直接获取此信息。 (虽然可能有某些方法我不知道阻止编译成功)

但是,我在这里质疑设计。一旦SomeLibraryClass完成,释放锁是不是更有意义?如果您担心多次调用AddFoo的效率,您的库可以提供接受std::vector<Foo>的成员,该成员只需获取并释放一次锁。

答案 4 :(得分:0)

为什么要提供公共addfoo方法?你说它是全部初始化,所以让集合被赋予构造函数。

然后,您可以从构造函数

调用非虚拟functocall