1.MFC程序中类的开始
化简:
MFC对话框程序最少包含一个从CWinApp
派生的类(这个类负责应用程序的初始化、运行和终止),必须重写 InitInstance
方法来进行应用程序的初始化。
如果你的应用程序包含对话框,那么通常会从CDialogEx
(或其前身CDialog
)派生一个类。
virtual
关键字用于指定一个成员函数在基类中被重写。
======================================================================
在Microsoft Foundation Classes (MFC)程序中,至少会包含几个关键的类,但具体包含哪些类取决于应用程序的类型。
以下是MFC对话框程序中通常包含的一些基本组件:
-
CWinApp:这是MFC应用程序的基类,每个MFC应用程序都必须有一个从
CWinApp
派生的类。这个类负责应用程序的初始化、运行和终止。 -
CDialogEx:这是MFC中用于创建对话框的基类。如果你的应用程序包含对话框,那么通常会从
CDialogEx
(或其前身CDialog
)派生一个类。
以下是MFC单文档界面(SDI)或多文档界面(MDI)应用程序通常包含的几个基本类:
-
CMainFrame:这是主框架窗口的类,通常从
CFrameWnd
或其派生类(如CMDIFrameWnd
或CFrameWndEx
)派生。 -
CView:这是视图类的基类,用于显示和操作文档数据。
-
CDocument:这是文档类的基类,用于管理应用程序的数据。
以下是一个简单的MFC SDI应用程序可能包含的类的例子:
class CMyApp : public CWinApp {
public:
virtual BOOL InitInstance();
};
class CMainFrame : public CFrameWnd {
// ...
};
class CMyView : public CView {
// ...
};
class CMyDoc : public CDocument {
// ...
};
class CMyDialog : public CDialogEx {
// ...
};
在这个例子中,CMyApp
是应用程序类,它必须重写 InitInstance
方法来进行应用程序的初始化。CMainFrame
是主框架窗口类,CMyView
是视图类,CMyDoc
是文档类,而 CMyDialog
是一个对话框类。
因此,一个基本的MFC程序至少包含一个从 CWinApp
派生的应用程序类,如果程序中有对话框,则至少包含一个从 CDialogEx
派生的对话框类。但通常还会有其他几个类来构成应用程序的框架。
======================================================================
在C++中,virtual
关键字用于指定一个成员函数在基类中被重写,这样它就可以在派生类中被重新定义,并且表现出多态的行为。以下是一些使用virtual
关键字的情况:
-
多态性:当你想要通过基类指针或引用调用派生类中的函数时,你应该在基类中将该函数声明为
virtual
。这样,即使指针或引用的类型是基类类型,调用的也会是派生类中重写的版本。 -
继承:在继承中,如果你希望派生类能够覆盖(override)基类中的某个函数,你应该在基类中将该函数声明为
virtual
。 -
虚析构函数:如果你有一个基类,它将被用作继承的起点,并且该基类有需要释放的资源(如动态分配的内存),你应该提供一个
virtual
析构函数。这样,当通过基类指针删除派生类对象时,可以确保正确的析构函数链被调用,从而防止资源泄漏。
以下是一些具体的使用场景:
-
基类定义接口:当你定义一个基类,它提供了通用的接口,而不同的派生类将提供具体的实现时。
-
工厂模式:在实现工厂模式时,你通常会定义一个基类,其中包含一个或多个
virtual
函数,然后通过派生类来创建具体的对象。 -
观察者模式:在观察者模式中,
virtual
函数可以用来通知观察者对象状态的变化。 -
策略模式:在策略模式中,不同的算法可以在派生类中实现,并通过基类的
virtual
函数来调用。
以下是一个简单的例子,展示了如何使用virtual
关键字:
class Base {
public:
virtual void DoSomething() {
// 基类的实现
}
virtual ~Base() {
// 虚析构函数
}
};
class Derived : public Base {
public:
void DoSomething() override {
// 派生类的实现,覆盖基类的DoSomething
}
};
int main() {
Base* b = new Derived();
b->DoSomething(); // 调用Derived类的DoSomething方法
delete b; // 正确地调用Derived类的析构函数,然后是Base类的析构函数
return 0;
}
在这个例子中,DoSomething
在基类中被声明为virtual
,因此在派生类中可以重写它。同样,基类的析构函数也是virtual
的,确保了通过基类指针删除派生类对象时能够正确地调用析构函数链。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构