【深入浅出MFC】第二章 Win32 基本程序观念
来源:互联网 发布:java三大框架书籍 编辑:程序博客网 时间:2024/06/11 22:37
1.类别及其成员- 谈封装(encapsulation)
member variable(成员变量)和member function(成员函数)
2.基础类别与衍生类别:谈继承(Inheritance)
1.子类拥有父类的所有属性和动作。
2.不同的子类可以继承父类一个相同的动作。
3. 既然所有类别都有display 动作,把它提升到老祖宗CShape 去,然后再继承
之,好吗?不好,因为display 函数应该因不同的形状而动作不同。
4. 如果display 不能提升到基础类别去,我们就不能够以一个for 循环或while
循环干净漂亮地完成下列动作(此种动作模式在对象导向程序方法中重要无
比):
CShape shapes[5];
// 令5 个shapes 各为矩形、四方形、椭圆形、圆形、三角形
for (int i=0; i<5; i++)
{
shapes[i].display;
}
3.this 指针
成员函数有一个隐藏参数,名为this 指针
void setcolor(int color) { m_color = color; }
void setcolor(int color, (CShape*)this) { this->m_color = color; }
4.虚拟函数与多态(Polymorphism)
1.要调用父类别的函数,你必须使用scope resolution operator(::)明白指出。
接下来我要触及对象类型的转换,这关系到指针的运用,更直接关系到为什么需要虚拟
函数。了解它,对于application framework 如MFC 者的运用十分十分重要。
接下来我要触及对象类型的转换,这关系到指针的运用,更直接关系到为什么需要虚拟
函数。了解它,对于application framework 如MFC 者的运用十分十分重要。
2. 如果你以一个「基础类别之指针」指向「衍生类别之对象」,那么经由该指针
你只能够调用基础类别所定义的函数。
你只能够调用基础类别所定义的函数。
3. 如果你以一个「衍生类别之指针」指向一个「基础类别之对象」,你必须先做
明显的转型动作(explicit cast)。这种作法很危险,不符合真实生活经验,在
程序设计上也会带给程序员困惑。
明显的转型动作(explicit cast)。这种作法很危险,不符合真实生活经验,在
程序设计上也会带给程序员困惑。
4. 如果基础类别和衍生类别都定义了「相同名称之成员函数」,那么透过对象指
针调用成员函数时,到底调用到哪一个函数,必须视该指针的原始型别而定,
而不是视指针实际所指之对象的型别而定。
针调用成员函数时,到底调用到哪一个函数,必须视该指针的原始型别而定,
而不是视指针实际所指之对象的型别而定。
虚拟函数正是为了对「如果你以一个基础类别之指针指向一个衍生类别之对象,那么透
过该指针你就只能够调用基础类别所定义之成员函数」这条规则反其道而行的设计。
过该指针你就只能够调用基础类别所定义之成员函数」这条规则反其道而行的设计。
如果没有虚拟函数这种东西,你还是可以使用scope resolution operator(::)明白指出调用
哪一个函数,但程序就不再那么优雅与弹性了。
哪一个函数,但程序就不再那么优雅与弹性了。
虚拟函数与document 有关的Serialize 函数和与view 有关的OnDraw 函数
多态(Polymorphism)
编译器无法在编译时期判断pEmp->computePay到底是调用哪一个函数,必须在执行时期才能评估之,这称为后期绑定late binding 或动
态绑定dynamic binding。
态绑定dynamic binding。
纯虚拟函数
virtual void display() = 0;virtual void display() = 0;
只要是拥有纯虚拟函数的类别,就是一种抽象类别,它是不能够被具象化(instantiate)的
■ 如果你期望衍生类别重新定义一个成员函数,那么你应该在基础类别中把此函
数设为virtual。
■ 以单一指令唤起不同函数,这种性质称为Polymorphism,意思是"the ability to
assume many forms",也就是多态。
■ 虚拟函数是C++ 语言的Polymorphism 性质以及动态绑定的关键。
77
■ 既然抽象类别中的虚拟函数不打算被调用,我们就不应该定义它,应该把它设
为纯虚拟函数(在函数声明之后加上"=0" 即可)。
■ 我们可以说,拥有纯虚拟函数者为抽象类别(abstract Class),以别于所谓的
具象类别(concrete class)。
■ 抽象类别不能产生出对象实体,但是我们可以拥有指向抽象类别之指针,以便
于操作抽象类别的各个衍生类别。
■ 虚拟函数衍生下去仍为虚拟函数,而且可以省略virtual 关键词。
数设为virtual。
■ 以单一指令唤起不同函数,这种性质称为Polymorphism,意思是"the ability to
assume many forms",也就是多态。
■ 虚拟函数是C++ 语言的Polymorphism 性质以及动态绑定的关键。
77
■ 既然抽象类别中的虚拟函数不打算被调用,我们就不应该定义它,应该把它设
为纯虚拟函数(在函数声明之后加上"=0" 即可)。
■ 我们可以说,拥有纯虚拟函数者为抽象类别(abstract Class),以别于所谓的
具象类别(concrete class)。
■ 抽象类别不能产生出对象实体,但是我们可以拥有指向抽象类别之指针,以便
于操作抽象类别的各个衍生类别。
■ 虚拟函数衍生下去仍为虚拟函数,而且可以省略virtual 关键词。
5.类别与对象大解剖
含有虚函数的类必定有一个指向虚函数表的指针
#include<iostream>using namespace std;class ClassA{public:int m_dataOne;int m_dataTwo;public:void funcOne() { }void funcTwo() { }virtual void vfuncOne() { }virtual void vfuncTwo() { }};class ClassB : public ClassA{public:int m_dataThree;public:void funcTwo() { }virtual void vfuncOne() { }};class ClassC : public ClassB{public:int m_dataOne;int m_dataFour;public:void funcTwo() { }virtual void vfuncOne() { }};void main(){std::cout<<sizeof(ClassA)<<std::endl;std::cout<<sizeof(ClassB)<<std::endl;std::cout<<sizeof(ClassC)<<std::endl;ClassA a;ClassB b;ClassC c;b.m_dataOne = 1;b.m_dataTwo = 2;b.m_dataThree = 3;c.m_dataOne = 1;c.m_dataTwo = 2;c.m_dataThree = 3;c.m_dataFour = 4;c.ClassA::m_dataOne = 111;cout<<b.m_dataOne<<endl;cout<<b.m_dataTwo<<endl;cout<<b.m_dataThree<<endl;cout<<c.m_dataOne<<endl;cout<<c.m_dataTwo<<endl;cout<<c.m_dataThree<<endl;cout<<c.m_dataFour<<endl;cout<<c.ClassA::m_dataOne<<endl;cout<<&b<<endl;cout<<&b.m_dataOne<<endl;cout<<&b.m_dataTwo<<endl;cout<<&b.m_dataThree<<endl;cout<<&c<<endl;cout<<&c.m_dataOne<<endl;cout<<&c.m_dataTwo<<endl;cout<<&c.m_dataThree<<endl;cout<<&c.m_dataFour<<endl;cout<<&c.ClassA::m_dataOne<<endl;system("pause");}
6.Object slicing 与虚拟函数
#include <iostream>using namespace std;class CObject{public:virtual void Serialize(){cout<<"COject::Serialize() \n\n";}};class CDocument : public CObject{public:int m_dataOne;virtual void Serialize(){cout<<"CDocument::Serialize() \n\n";}void func(){cout<<"CDocument::func()"<<endl;Serialize();}};class CMyDoc : public CDocument{public:int m_dataTwo;virtual void Serialize(){cout<<"CMyDoc::Serialize() \n\n";}};void main(){CMyDoc mydoc;CMyDoc* pmydoc = new CMyDoc;cout<<"#1 testing"<<endl;mydoc.func();cout<<"#2 testing"<<endl;((CDocument*)(&mydoc))->func();cout<<"#3 testing"<<endl;pmydoc->func();cout<<"# 4testing"<<endl;((CDocument)mydoc).func();system("pause");}
经过data slicing 把mydoc变成了一个完完全全的CDocument对象了。
其中(CDocument)mydoc强制转换将会把对象的内容分割。
7.静态成员(函数和变量)
static double m_rate;
static成员变量不是对象的一部分,而是类的一部分,所以程序还没有诞生对象的时候就由此成员变量了。
static成员变量不要安排在构造函数中,也不要安排在头文件中,因为它可能被执行很多次。
double Saving::m_rate = 0.0075
Saving::m_rate = 0.0075 //需把m——rate改为public。
如果希望在产生object之前就存取class中的private static成员变量,就设计一个static成员函数。
static void setRate(double newRate){m_rate = newRate;}
8.C++程序的生与死:构造与析构函数
1.new 不但配置对象所需的内存空间,而且会引发构造函数的执行。
2. 全局对象:程序开始就构造函数,程序结束前析构。
静态对象:程序诞生时构造函数执行,程序结束前析构但是比全局对象早。
new出来的局部对象:诞生时构造函数执行,delete时析构。
局部对象:执行到的时候构造,局部函数结束时析构。
- 【深入浅出MFC】第二章 Win32 基本程序观念
- 【深入浅出MFC】第一章 Win32 基本程序观念
- <<深入浅出MFC>>笔记1——Win32基本程序观念
- MFC学习笔记1--Win32基本程序观念
- 1.Win32基本程序概念(深入浅出MFC之读书笔记)
- 一、Win32基本程序观念 (学习笔记)
- 《深入浅出MFC》 第二章
- MFC深入浅出-Win32程序开发流程
- 《深入浅出MFC》学习笔记一 : Win32基本程序概念 (转)
- 深入浅出MFC笔记2-MFC程序如何包装Win32程序
- 深入浅出MFC学习笔记:(第一章:win32基本概念,第二章:C++的重要性质)
- 深入浅出MFC学习笔记:(第一章:win32基本概念,第二章:C++的重要性质)
- 深入浅出MFC笔记1-Win32和MFC程序对比
- 深入浅出MFC笔记第二章
- 深入浅出MFC(第二章)
- 《MFC深入浅出》学习笔记--------Win32 SDK 程序开发流程
- 第二章 Win32程序运行原理
- Win32开发MFC程序
- CentOS-6.3(Linux) 命令行 DSL 拨号
- C++虚函数、多态、继承
- linux-0.11调试教程,update_line()函数中按下退格键时对应的缓冲区
- 7.4.1八皇后问题(经典回溯法)
- Android模拟器
- 【深入浅出MFC】第二章 Win32 基本程序观念
- HIBERNATE错误集锦
- 如何杀掉defunct进程
- 旋转卡壳算法
- Hibernate 第十讲 表关联关系(二)双向项一对一外键关联
- Oracle 10g 下载地址(备忘)
- 一致性hash
- 根据安装好的第一个linux虚拟机节点怎么创建相同的第二和第三个虚拟机节点
- pat 1032 Sharing