如何在MFC中正确继承对话框

how to inherit dialogs correctly in MFC

本文关键字:继承 对话框 MFC      更新时间:2023-10-16

我正在用OpenGL和MFC在C++中构建一个3d画家。我创建了对话框来创建我拥有的每一个形状:比如立方体、圆柱体等等。。。我的多维数据集类继承了圆柱体类,只是堆栈和切片的数量不同。因此,"CreateCylinder"对话框应与"CreateCube"对话框外观相同。我能够很好地继承它,但我有一个错误,说:

Error   6   error C2065: 'IDD_BASEWIN_DIALOG' : undeclared identifier   c:usersl122desktopopenglopenglbasewindlg.h    19  1   OpenGL

这种情况在每次新编译时都会发生,只需对代码进行一些小的更改。

为了修复它,我评论这行:

enum { IDD = IDD_BASEWIN_DIALOG };

然后编译并取消注释同一行,这有助于在下一次编译中正常工作。

这就是我在CreateCube对话框类中继承CreateCylinder对话框类的方式:

IMPLEMENT_DYNAMIC(CreateCube, CreateCylinder)
CreateCube::CreateCube()
: CreateCylinder(this->GetSafeOwner())
{
}
CreateCube::~CreateCube()
{
}

void CreateCube::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    CreateCylinder::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CreateCube, CreateCylinder)
END_MESSAGE_MAP()

我还在CreateCylinder构造函数中编辑了这一行:

CreateCylinder::CreateCylinder(CWnd* pParent /*=NULL*/)
: CDialogEx(CreateCylinder::IDD, this->GetSafeOwner())

头文件:

#pragma once
#include "CreateCylinder.h"
// CreateCube dialog
class CreateCube : public CreateCylinder
{
    DECLARE_DYNAMIC(CreateCube)
public:
    CreateCube();   // standard constructor
    virtual ~CreateCube();
// Dialog Data
    enum { IDD = IDD_CREATE_CUBE_DLG };
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    DECLARE_MESSAGE_MAP()
};

我想知道我在继承上做错了什么。有必要像我一样将父对象的指针发送到基本对话框吗?上面的错误与此有关吗?

这里的问题是enum符号IDD_CREATE_CUBE_DLG的范围。当您继承一个类时,您不会继承它的"符号范围",而只是继承它的"成员名称空间"。我相信一些语言律师可以给出更精确(技术上正确)的解释。但是,一个简单的解释是,您不继承符号,因此枚举定义。即使它们在受保护的范围内,您也应该能够访问它们。

因此,假设IDD_CREATE_CUBE_DLGCreateCylinder类中用于设置"其"IDD,那么,而不是:

enum { IDD = IDD_CREATE_CUBE_DLG };

你应该写:

enum { IDD = CreateCylinder::IDD };

我认为正确的措辞是说你需要"完全合格"的名字。

这实际上是一件好事,一些类库用它来耍花招,比如枚举类支持的消息,等等——例如,请参阅FOX(小部件)工具包库。

更新:如果您按照此处更新的方式更改声明,从而避免使用IDD_CREATE_CUBE_DLG,那么您很可能不会再遇到IDD_CREATE_CUBE_DLG的问题。但是,如果你仍然这样做,问题将是IDD_CREATE_CUBE_DLG,因为它是在Resource.h中声明的,那么,在使用它时(这是报告错误的行),Resource.h没有(正确地)包括在内。因此,请检查报告错误时编译的.cpp文件是什么。然后检查该文件中的includes。您应该清理它们,但是,对于初学者来说,您可以"只"在(.h文件的)顶部的#include "Resource.h"

至于CDialogEx的构造函数,只需传递参数,如下所示:

CreateCylinder::CreateCylinder(CWnd* pParent)
: CDialogEx(CreateCylinder::IDD, pParent)

实际上,将resource.h添加到我的基本对话框头中解决了这个问题。在添加继承的类之前,我无法理解它是如何完美工作的。在这两种情况下,都没有包括这个头文件,那么它最初是如何工作的呢?