多态原理探究
理论知识:
- 当类中声明虚函数时,编译器会在类中生成一个虚函数表
- 虚函数表是一个存储类成员函数指针的数据结构
- 虚函数表是由编译器自动生成与维护的
- virtual成员函数会被编译器放入虚函数表中
- 当存在虚函数时,每个对象中都有一个指向虚函数表的指针(C++编译器给父类对象、子类对象提前布局vptr指针;当进行howToPrint(Parent *base)函数是,C++编译器不需要区分子类对象或者父类对象,只需要再base指针中,找vptr指针即可。)
- VPTR一般作为类对象的第一个成员
证明vptr指针存在
#include <iostream> using namespace std; class Parent1 { public: Parent1(int a=0) { this->a = a; } void print() { cout<<"我是父类"<<endl; } private: int a; }; class Parent2 { public: Parent2(int a=0) { this->a = a; } virtual void print() { cout<<"我是父类"<<endl; } private: int a; }; void main() { printf("sizeof(Parent):%d sizeof(Parent2):%d \n", sizeof(Parent1), sizeof(Parent2)); cout<<"hello..."<<endl; system("pause"); return ; }
输出结果
构造函数中调用虚函数能发生多态吗?
#include <iostream> using namespace std; //构造函数中调用虚函数能发生多态吗? class Parent { public: Parent(int a=0) { this->a = a; print();//在父类中执行虚函数 } virtual void print() { cout<<"我是父类"<<endl; } private: int a; }; class Child : public Parent { public: Child(int a = 0, int b=0):Parent(a) { this->b = b; print();//在子类中执行虚函数 } virtual void print() { cout<<"我是子类"<<endl; } private: int b; }; void HowToPlay(Parent *base) { base->print(); //有多态发生 //2 动手脚 } void main() { Child c1; //定义一个子类对象 ,在这个过程中,在父类构造函数中调用虚函数print 能发生多态吗? //c1.print(); cout<<"hello..."<<endl; system("pause"); return ; }
父类指针和子类指针的步长
1) 铁律1:指针也只一种数据类型,C++类对象的指针p++/--,仍然可用。
2) 指针运算是按照指针所指的类型进行的。
p++《=》p=p+1 //p = (unsigned int)basep + sizeof(*p) 步长。
3) 结论:父类p++与子类p++步长不同;不要混搭,不要用父类指针++方式操作数组。
纯虚函数和抽象类
#include<iostream> using namespace std; //面向抽象类编程(面向一套预先定义好的接口编程) //解耦合 ....模块的划分 class Figure//抽象类 { public: //约定一个统一的界面(接口)让子类使用 让子类必须去实现 virtual void getArea()=0;//纯虚函数 protected: private: }; //圆形 class Circle:public Figure { public: Circle(int a,int b) { this->a; this->b; } virtual void getArea() { cout<<"圆形的面积:"<<3.14*a*a<<endl; } private: int a; int b; }; //三角形 class Tri:public Figure { public: Tri(int a,int b) { this->a; this->b; } virtual void getArea() { cout<<"三角形的面积:"<<a*b/2<<endl; } private: int a; int b; }; //四边形 class Square:public Figure { public: Square(int a,int b) { this->a; this->b; } virtual void getArea() { cout<<"四边形的面积:"<<a*b<<endl; } private: int a; int b; }; void objplay(Figure *base) { base->getArea();//会发生多态 } void main() { //Figuer f;//抽象类不能被实例化 Figure *base=NULL; Circle c1(10,20); Tri t1(20,30); Square s1(50,60); objplay(&c1); objplay(&t1); objplay(&s1); system("pause"); }
编写一个C++程序, 计算程序员( programmer )工资
1 要求能计算出初级程序员( junior_programmer ) 中级程序员 ( mid_programmer )高级程序员( adv_programmer)的工资
2 要求利用抽象类统一界面,方便程序的扩展, 比如:新增, 计算 架构师 (architect ) 的工资
#include<iostream> using namespace std; /* 编写一个C++程序, 计算程序员( programmer )工资 1 要求能计算出初级程序员( junior_programmer ) 中级程序员 ( mid_programmer )高级程序员( adv_programmer)的工资 2 要求利用抽象类统一界面,方便程序的扩展, 比如:新增, 计算 架构师 (architect ) 的工资 */ class programmer { public: virtual void getSal()=0; private: }; //初级程序员( junior_programmer ) class junior_programmer:public programmer { public: junior_programmer(char *name,char *job,int sal) { this->name=name; this->job=job; this->sal=sal; } virtual void getSal() { cout<<name<<" "<<job<<" : "<<sal<<endl; } protected: private: char *name; char *job; int sal; }; //中级程序员 ( mid_programmer ) class mid_programmer:public programmer { public: mid_programmer(char *name,char *job,int sal) { this->name=name; this->job=job; this->sal=sal; } virtual void getSal() { cout<<name<<" "<<job<<" : "<<sal<<endl; } protected: private: char *name; char *job; int sal; }; //高级程序员( adv_programmer) class adv_programmer:public programmer { public: adv_programmer(char *name,char *job,int sal) { this->name=name; this->job=job; this->sal=sal; } virtual void getSal() { cout<<name<<" "<<job<<" : "<<sal<<endl; } protected: private: char *name; char *job; int sal; }; //架构师 class architect:public programmer { public: architect(char *name,char *job,int sal) { this->name=name; this->job=job; this->sal=sal; } virtual void getSal() { cout<<name<<" "<<job<<" : "<<sal<<endl; } protected: private: char *name; char *job; int sal; }; //计算函数 简单的框架 void CalProgSal(programmer *base) { base->getSal(); } void main() { junior_programmer jp("小王","初级",4000); mid_programmer mp("小张","中级",8600); adv_programmer ap("小李","高级",15000); //系统扩展 architect ar("小高","架构师",24000); CalProgSal(&jp); CalProgSal(&mp); CalProgSal(&ap); CalProgSal(&ar); system("pause"); }
案例:socket库c++模型设计和实现
企业信息系统框架集成第三方产品
案例背景:一般的企业信息系统都有成熟的框架。软件框架一般不发生变化,能自由的集成第三方厂商的产品。
案例需求:请你在企业信息系统框架中集成第三方厂商的Socket通信产品和第三方厂商加密产品。
第三方厂商的Socket通信产品:完成两点之间的通信;
第三方厂商加密产品:完成数据发送时加密;数据解密时解密。
案例要求:
1)能支持多个厂商的Socket通信产品入围
2)能支持多个第三方厂商加密产品的入围
3)企业信息系统框架不轻易发生框架
需求实现
思考1:企业信息系统框架、第三方产品如何分层
思考2:企业信息系统框架,如何自由集成第三方产品
(软件设计:模块要求松、接口要求紧)
思考3:软件分成以后,开发企业信息系统框架的程序员,应该做什么?
第三方产品入围应该做什么?
编码实现
分析有多少个类 CSocketProtocol CSckFactoryImp1 CSckFactoryImp2
CEncDesProtocol HwEncdes ciscoEncdes
1、 定义 CSocketProtocol 抽象类
2、 编写框架函数
3、 编写框架测试函数
4、 厂商1(CSckFactoryImp1)实现CSocketProtocol、厂商2(CSckFactoryImp1)实现CSocketProtocol
5、 抽象加密接口(CEncDesProtocol)、加密厂商1(CHwImp)、加密厂商2(CCiscoImp)),集成实现业务模型
6、 框架(c语言函数方式,框架函数;c++类方式,框架类)
几个重要的面向对象思想
继承-组合(强弱)
注入
控制反转 IOC
MVC
面向对象思想扩展aop思想
aop思想是对继承编程思想的有力的补充