C++ 在从模板化中介派生的类中调用非模板基类构造函数 模板 类屏幕助手:公共WndClass { 公众: typedef WndClass基类; typedef typename屏幕助手类; 正确的GetControlRect(CWnd*PCControl)常量 { 正确的矩形窗口(0,0,0,0); 如果(!pControl) 返回窗口; pControl->GetWindowRect(&rectWindow); 此->ScreenToClient(&rectWindow); 返回窗口; } }; 类MyDialog:公共屏幕助手 { 公众: typedef屏幕助手::基类MDialog; MyDialog(int i); MyDialog(LPCSTR lpszTemplateName,CWnd*pParentWnd); MyDialog(int-nIDTemplate,CWnd*pParentWnd); }; MyDialog::MyDialog(inti) { 基类b; } MyDialog::MyDialog(LPCSTR lpszTemplateName,CWnd*pParentWnd) :MyDialog::基类(lpszTemplateName,pParentWnd) { } MyDialog::MyDialog(int-nIDTemplate,CWnd*pParentWnd) :MyDialog::CDialog(nIDTemplate,pParentWnd) { }
我不明白为什么我不能打电话给基本的屏幕助手C++ 在从模板化中介派生的类中调用非模板基类构造函数 模板 类屏幕助手:公共WndClass { 公众: typedef WndClass基类; typedef typename屏幕助手类; 正确的GetControlRect(CWnd*PCControl)常量 { 正确的矩形窗口(0,0,0,0); 如果(!pControl) 返回窗口; pControl->GetWindowRect(&rectWindow); 此->ScreenToClient(&rectWindow); 返回窗口; } }; 类MyDialog:公共屏幕助手 { 公众: typedef屏幕助手::基类MDialog; MyDialog(int i); MyDialog(LPCSTR lpszTemplateName,CWnd*pParentWnd); MyDialog(int-nIDTemplate,CWnd*pParentWnd); }; MyDialog::MyDialog(inti) { 基类b; } MyDialog::MyDialog(LPCSTR lpszTemplateName,CWnd*pParentWnd) :MyDialog::基类(lpszTemplateName,pParentWnd) { } MyDialog::MyDialog(int-nIDTemplate,CWnd*pParentWnd) :MyDialog::CDialog(nIDTemplate,pParentWnd) { },c++,templates,mfc,constructor,base-class,C++,Templates,Mfc,Constructor,Base Class,我不明白为什么我不能打电话给基本的屏幕助手 如果MyDialog继承自screenhelpers,screenhelpers继承自CDialog,为什么我不能调用CDialog?构造函数中的初始化列表只能调用其直接父级的构造函数,而不能调用链上的构造函数。这就是为什么不能直接初始化CDialog screenhelpers类没有定义一个接受两个参数的构造函数,所以这也不起作用。即使您添加了这样一个构造函数,我也不确定用typedefed名称引用它是否有效,您可能需要使用屏幕帮助程序。如果MyDi
如果MyDialog继承自screenhelpers,screenhelpers继承自CDialog,为什么我不能调用CDialog?构造函数中的初始化列表只能调用其直接父级的构造函数,而不能调用链上的构造函数。这就是为什么不能直接初始化CDialog
screenhelpers类没有定义一个接受两个参数的构造函数,所以这也不起作用。即使您添加了这样一个构造函数,我也不确定用typedefed名称引用它是否有效,您可能需要使用
屏幕帮助程序
。如果MyDialog
构造函数被允许调用CDialog
构造函数,后者将被调用两次:一次由MyDialog
调用,一次由screenhelopers
调用。那将是一场灾难
如果需要控制如何从MyDialog
调用CDialog
构造函数,则需要使用虚拟继承:
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)
{
}
模板
类屏幕助手:公共虚拟WndClass
然后,您将拥有(不仅仅能够)从MyDialog
调用CDialog
构造函数
请注意,这可能会对您的设计产生其他影响。我有另一个简化示例
类Bob{public:Bob():t(12){}Bob(inti):t(I){}intt;};模板类Bill:public-Base{public:Bill():s(20){}typedef-Base-BaseClass;int-s;};类it:public-Bill{public:it(inti){s=i;t=1;}//创建明确初始化驻留在Bob#if 1//我的未加工尝试it中的t的上面行的等价项(双d):基类(30){}#endif}代码>it构造函数正在修改t,它是Bob的一个成员,因此证明了基类Bob存在于it中。如果您能指出您遇到的错误,我不得不在我的答案中猜测。Oohps。尝试使用typedef错误C2614:“MyDialog”:非法成员初始化:“BaseClass”不是基或成员
以及尝试使用CDialog错误C2614:“MyDialog”:非法成员初始化:“CDialog”不是基或成员
GCC 4.6.1说明:“错误:ISO C++禁止嵌套类型的屏幕帮助器,它与封闭类同名[FPrime]。“这就是说,将类typedef添加到类的类型本身并不真正有意义,因为您已经拥有了该类的类型。@Kerrek-a ThisClass typedef可以,但跳过不正确的typename
可能会使编译器更高兴?@Bo:确实如此!:-)所以(为什么)这是一个有用的想法吗?@Kerrek你能再解释一下吗?@Stone:我的意思是,为什么你需要一个typedef来引用你已经拥有的类型?假设你说typedef屏幕助手Foo代码>。现在您有了Foo::ThisClass
,但为什么它与Foo
相同呢!在什么情况下您需要这个类
?
template <class WndClass>
class screenhelpers : public virtual WndClass