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

Calling non-template base class constructor in class derived from templated intermediary

本文关键字:调用 构造函数 基类 派生      更新时间:2023-10-16
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)
{
}

我不明白为什么我不能调用屏幕助手的基类。

如果MyDialog继承自屏幕助手,屏幕助手继承自CDialog,为什么我不能调用CDialog?

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

你的屏幕助手类没有定义一个带两个参数的构造函数,所以这也不能工作。即使您添加了这样的构造函数,我也不确定通过类型定义的名称引用它的语法是否有效,您可能需要使用screenhelpers<CDialog>来代替。

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

如果你需要控制如何从MyDialog调用CDialog构造函数,你需要使用虚拟继承:

template <class WndClass>
class screenhelpers : public virtual WndClass

那么你将(不只是能够)从MyDialog调用CDialog构造函数。

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