父类可能会调用其子类版本的函数
问题描述:
我有一个基类自选画面&我希望始终在其构造函数中调用函数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(...);
}
};
答
不,你不能这样做。在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);
}
};
};
只是要注意在这两个基地和派生类中的内部类。你的情况可以忽略互斥锁和模板的东西。
不可以。把你的构建逻辑放在构造函数中。 – 2011-04-22 11:00:12