在从模板化中介派生的类中调用非模板基类构造函数

时间:2011-07-14 16:27:09

标签: c++ templates mfc constructor base-class

template <class WndClass>
class screenhelpers : public WndClass
{
public:
    typedef WndClass BaseClass;
    typedef typename screenhelpers<WndClass> ThisClass;
    CRect GetControlRect(CWnd *pControl) const
    {               
            CRect rectWindow(0,0,0,0);
            if (!pControl)
                    return rectWindow;
            pControl->GetWindowRect(&rectWindow);
            this->ScreenToClient(&rectWindow);
            return rectWindow;
    }
};

class MyDialog : public screenhelpers<CDialog>
{
public:
    typedef screenhelpers<CDialog>::BaseClass MDialog;
    MyDialog(int i);
    MyDialog(LPCSTR lpszTemplateName, CWnd *pParentWnd);
    MyDialog(int nIDTemplate, CWnd *pParentWnd);
};

MyDialog::MyDialog(int i)
{
    BaseClass b;    
}

MyDialog::MyDialog(LPCSTR lpszTemplateName, CWnd *pParentWnd)
:    MyDialog::BaseClass(lpszTemplateName, pParentWnd)
{    
}


MyDialog::MyDialog(int nIDTemplate, CWnd *pParentWnd)
    :       MyDialog::CDialog(nIDTemplate, pParentWnd)
{
}

我不明白为什么我似乎无法调用screenhelpers的基类。

如果MyDialog继承了屏幕截图,并且屏幕截图继承自CDialog,为什么我不能调用CDialog?

2 个答案:

答案 0 :(得分:3)

构造函数中的初始化列表只能调用其直接父级的构造函数,而不能调用其直接构造函数。这就是为什么你不能直接初始化CDialog。

你的screenhelpers类没有定义一个带有两个参数的构造函数,所以它也不会起作用。即使您添加了这样的构造函数,我也不确定它是由typedefed名称引用它的有效语法,您可能需要使用screenhelpers<CDialog>代替。

答案 1 :(得分:1)

如果允许MyDialog构造函数调用CDialog构造函数,后者将被调用两次:一次调用MyDialog,一次调用screenhelpers。那将是一场灾难。

如果您需要控制从CDialog调用MyDialog构造函数的方式,则需要使用虚拟继承:

template <class WndClass>
class screenhelpers : public virtual WndClass

然后您 (不仅仅是)能够从CDialog调用MyDialog构造函数。

请注意,这可能会对您的设计产生其他影响。