父类可能会调用其子类版本的函数

问题描述:

我有一个基类自选画面&我希望始终在其构造函数中调用函数initComponents(),即使对于此类的子类也是如此。但是如果子类已经覆盖了initComponents()函数,那么我想让MyClass调用子类的initComponents()版本,而不是initComponents()的超类(MyScreen)版本。父类可能会调用其子类版本的函数

是否有可能在MyClasses构造函数中做到这一点?

class MyScreen 
{ 
    public: 
    MyScreen() 
    { 
     // a child of this class (& any instance of this class) should always call the initComponents() from this constructor 
     initComponents(); 
    } 

    void initComponents() 
    { 
     // initialise mainLayout, etc, usually this function wont be overridden, sometimes it will be 
    } 

    protected: 
     Layout *mainLayout; 
}; 

class MenuScreen : public MyScreen 
{ 
    public: 
    MenuScreen : public MyScreen() 
    { 
     // I know I could just call initComponents from here, but this is just an example, somethings must be called from the base class 
    } 

    void initComponents() 
    { 
     // create layout, set main layout etc. 
     mainLayout = new MenuLayout(...); 
    } 
}; 
+0

不可以。把你的构建逻辑放在构造函数中。 – 2011-04-22 11:00:12

不,你不能这样做。在MyScreen的构造函数中,该对象的动态类型始终为MyScreen。你不能从里面调用MenuScreen函数。

你不应该(或者甚至不能)这样做。问题是,当构造派生类的对象时,基类构造函数总是在派生类之前调用​​。这意味着派生对象还没有被创建,所以它的成员不会被初始化(这可能对v表也是有效的,所以虚函数调用将不起作用)。检查this article

相反,你应该用你的类的用户显式调用的initComponents并将其标记虚拟

填充的资源通过调用虚函数是通过使用内部类可以。下面是一个例子

#ifndef CLAZYSTATICRESOURCINITIALIZATIONASPECT_H 
#define CLAZYSTATICRESOURCINITIALIZATIONASPECT_H 

#include <boost/thread/mutex.hpp> 

template <typename R> 
class CLazyStaticResourceInitialization 
{ 
public: 

    /** 
    * Destructor 
    */ 
    virtual ~CLazyStaticResourceInitialization() 
    { 
    } 

protected: 

    /** 
    * Internal class used for calling virtual function from constructor 
    */ 
    struct parent_virtual 
    { 
     /** 
     * Virtual destructor 
     */ 
     virtual ~parent_virtual() 
     { 
     } 
     /** 
     * Virtual method implemented by parent class is necessary 
     */ 
     virtual void initializeOnce() const 
     { 
     } 
    }; 

    /** 
    * Constructor that can call a virtual function of the parent 
    * @param obj specifies the virtual function 
    */ 
    CLazyStaticResourceInitialization(const parent_virtual& obj) 
    { 
     boost::mutex::scoped_lock scoped_lock(m_Mutex); 

     //Initialize the resource only once 
     if (isInitialized() == false) 
     { 
      obj.initializeOnce(); 

      setInitialized(); 
     } 
    } 

    /** 
    * Returns if any instance of this class has been initialized or not 
    * @return true if initialized, false otherwise 
    */ 
    bool isInitialized() const 
    { 
     return m_bInitialized;; 
    } 

    /** 
    * Returns if any instance of this class has been initialized or not 
    */ 
    void setInitialized() 
    { 
     m_bInitialized = true; 
    } 

protected: 

    /** 
    * The flag that indicates whether this class is initialized or not 
    */ 
    static volatile bool m_bInitialized; 

    /** 
    * The resource instance 
    */ 
    static R  m_Resource; 

    /** 
    * The mutex to protect initialized flag 
    */ 
    static boost::mutex  m_Mutex; 


}; 

//Assume that this class is not initialized in the beginning 
template <typename R> volatile bool CLazyStaticResourceInitialization<R>::m_bInitialized = false; 

//Create a static instance of resource 
template <typename R> R CLazyStaticResourceInitialization<R>::m_Resource; 

//Create a static instance of mutex 
template <typename R> boost::mutex CLazyStaticResourceInitialization<R>::m_Mutex; 


#endif 

这里是你如何使用它

class CTestLazyInitialized : public CLazyStaticResourceInitialization <std::vector<int> > 
{ 
public: 
    CTestLazyInitialized(): 
    CLazyStaticResourceInitialization<std::vector<int> >(lazyderived_virtual()) 
    { 
    } 

    unsigned int size() 
    { 
     return this->m_Resource.size(); 
    } 
protected: 

    struct lazyderived_virtual : public CLazyStaticResourceInitialization <std::vector<int> >::parent_virtual 
    { 

     lazyderived_virtual() 
     { 
     } 

     void initializeOnce() const 
     { 
      m_Resource.push_back (1); 
     } 

    }; 
}; 

只是要注意在这两个基地和派生类中的内部类。你的情况可以忽略互斥锁和模板的东西。