我有一个基类MyScreen&我想始终在其构造函数中调用函数initComponents(),即使对于此类的子类也是如此。但是如果子类重写了initComponents()函数,那么我希望MyClass调用initComponents()的子类版本而不是initComponents()的超类(MyScreen)版本。 / p>
是否可以在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 :(得分:3)
你不应该(或者甚至不能)这样做。问题是,在构造派生类的对象时,总是在派生类之前调用基类构造函数。这意味着尚未创建派生对象,因此其成员将不会被初始化(这可能对v表也有效,因此虚函数调用将不起作用)。检查this article
相反,您应该明确地由您的类的用户调用initComponents并将其标记为虚拟
答案 1 :(得分:1)
不,你不能这样做。对象的动态类型始终是MyScreen
的构造函数中的MyScreen
。你不能从里面调用MenuScreen
函数。
答案 2 :(得分:0)
通过使用内部类可以通过调用虚函数来填充资源。这是一个例子
#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);
}
};
};
注意基类和派生类中使用的内部类。对于您的情况,可以忽略互斥锁定和模板内容。