- 1、本文档共23页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
为WTL设计一个“文档视图”模型
为WTL设计一个“文档-视图”模型
作者:戴霖 bill.dai@163.com前言 2
1- 编译期虚函数调用 嵌入类 3
2- 文档类 4
3- 视图类 5
4- 文档模板类 6
5- 文档模板管理器类 6
6- 上下文信息——CCreateContext 6
7- 改造你的代码 7
8- 模型的工作流程 10
9- 实现代码 11
10- 后记 22
前言
WTL(Windows Template Library,Windows模板库)提供了比MFC库更加精减的代码框架,这其中就省略了对MFC“文档-视图”模型的支持。而“文档-视图”模型的核心思想——将数据和其表示分开,在开发大型软件时颇为有用。那如何既能保留WTL精减方便的优点,又能拥有MFC“文档-视图”模型的精髓呢?本文将探讨一种方法,在为WTL引入“文档-视图”模型的同时,让其接口尽可能地接近于MFC,从而方便实际应用。
我们将构建四个主要的类来实现“文档-视图”模型的行为,分别是文档类、视图类、文档模板类和文档模板管理器类。四部分的关系如下图:
由于WTL是构建在ATL基础之上的,所以其代码风格迥异于MFC,包含了大量的C++模板类代码。即使你能毫不费力地读懂它们,但是下面的仍然可能让你一头雾水:
Class CMyWin : public CWindowImplCMyWin
{
……
};
这样做是合法的,类名CMyWin已经被列入递归继承列表,是可以使用的。可是为什么要这样做呢?目的何在?这里蕴含了两个概念,一是编译期间的虚函数调用机制,二是嵌入类。1- 编译期虚函数调用 嵌入类
如果你想了解它们如何工作,请看下面的例子;如果你已经有了很好的ATL基础,那么可以直接跳过本章。
例子:
template class T
class Base
{protected:
void SayHello()
{
cout Hello Base;
}
public:
void Print()
{
T* ptr = static_castT*(this); // 这里我们称之为编译期虚函数调用 ptr-SayHello();
}
};
class Deriver1 : public BaseDeriver1
{/*空类*/};
class Deriver2 : public BaseDeriver2
{
protected:
void SayHello()
{
cout Hello Deriver2;
}
};
main()
{
Deriver1 d1;
Deriver2 d2;
d1.Print(); // 显示Hello Base
d2.Print(); // 显示Hello Deriver2
}
这句代码static_castT*(this) 就是窍门所在。它函数调用时将指向Base类型的指针this为Deriver1或D的指针因为模板代码是在编译期间生成的,所以只要编译器生成正确的继承列表,这就是安全的。因为在这this只能是指向D 1或D 2类型的对象,不会是其他的东西。这很像C++的多态性,只是Print()方法不是虚函数。
要解释这是如何工作的,首先看对每个Print()函数的调用,,对象Base被指派为Deriver1,所以代码被解释成:
void BaseDeriver1::Print()
{
Deriver1* ptr = static_castDeriver1*(this);
ptr-SayHello();
}
由于Deriver1没有重载SayHello(),所以查看基类Base,Base有SayHello(),所以Base的SayHello()被调用。
再看,这一次对象被指派为Deriver2类型,Print()被解释成:
void BaseDeriver2::Print()
{
Deriver2* ptr = static_castDeriver2*(this);
ptr-SayHello();
}
这一次,Deriver2含有SayHello()方法,所以Deriver2的SayHello()方法被调用。
这种技术的在于:
不需要使用指向对象的指针。
不需要虚函数表节省内存。
因为没有虚函数表所以运行时不发生调用空指针指向的虚函数。
所有的函数调用在编译时确定,而非C++虚函数机制使用的动态联编,这有利于编译程序对代码的优化。
读到这里你应该可以明白什么是编译期间的虚函数调用机制,那么嵌入类又是什么呢?其实这是ATL引入的一个概念,或者叫作“另一种继承机制”更合
文档评论(0)