C++_封装 、继承 、多态

C++的三大特征:封装 、继承 、多态。
封装突破了C语言函数的概念,可以隐藏实现细节,使得代码模块化
继承可以扩展已存在的模块,它们目的都是为了:代码重用。而多态是为了实现另一个目的:接口重用

封装:隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别;将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。封装的目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口,以特定的访问权限来使用类的成员。简而言之,应该给你看的你可以看见,不应该给你看的你看不见。

访问限定符:
public:共有成员函数声明 、任意位置、类中类外
protected:保护成员函数声明 、本类和子类类中访问
private:私有成员函数声明 、仅本类类中访问

继承:是指可以让某个类型的对象获得另一个类型的对象的属性的方法。它支持按级分类的概念。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。 通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”。继承的过程,就是从一般到特殊的过程。要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。继承概念的实现方式有二类:实现继承与接口继承。实现继承是指直接使用基类的属性和方法而无需额外编码的能力;接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力,一个对象直接使用另一对象的成员变量和成员方法、构造函数和析构函数不能被继承,基类的构造优先于派生类的构造。

继承方式:
1、public:公有继承、本类的公有成员和保护成员可以作为其派生类的公有成员和保护成员,派生类的成员函数可以访问本类中、公有成员和保护成员,无法访问本类中的私有成员、派生类的对象可以访问本类的公有成员
2、protected:保护继承、私有继承、本类的所有公有成员和保护成员都成为派生类的保护成员、本类的公有成员和保护成员只能被它的直接派生类成员函数或友元访问
3、private:本类的公有成员和保护成员都作为其派生类的私有成员、在私有继承时,本类的成员只能由直接派生类访问,而无法再往下继承

继承关系图:基类中不同访问限定符下的成员以不同的继承方式继承在派生类中的访问限定

 publicprotectedprivate
publicpublicprotected不可访问
protectedprotectedprotected不可访问
privateprivateprivate不可访问

类和类的关系
组合   a part of  has_a    
继承   a kind of  is_a
代理 

多态:一个实体同时具有多种形式,同一接口不同形态,就是指一个类实例的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们可以通过相同的方式予以调用。

多态分类:
静多态:编译确定函数调用     静态绑定  早绑定
动多态:运行确定函数调用     动态绑定  晚绑定
宏多态:预编译 

实现多态有以下方法:
虚函数:
virtual修饰符开始的成员函数
抽象类:拥有纯虚函数的类称,抽象类不能实例化对象,指针或引用
重载、覆盖、模版

重载:即重定义
三要素:同名、不同作用域、同参

隐藏:派生类中同名函数会隐藏基类中所有的同名函数,函数名相同,参数列表相同,但没有virtual修饰或函数名相同,参数列表不同,无论有无virtual修饰都是隐藏。
要素:同名、不同作用域、继承

覆盖:重写,基类中同名同参的函数是虚函数,派生类中同名同参的函数也是虚函数,派生类中同名同参的函数覆盖了基类中同名同参的虚函数
要素:不同作用域、继承、虚函数、同名、同参 

基类的指针或引用指向或者引用派生类对象

虚函数机制
        vftable:存放 RTTI  偏移   虚函数的入口地址
        vfptr:vfptr优先级最高  
        vftable:1.编译阶段、2..rodata、3.一个类拥有一张虚表  

哪些函数能成虚函数?1、可以取地址、2、依赖对象调用 
全局的普通函数        x  
普通的类成员方法    v
静态的成员方法        x
inline函数                 x
构造函数                  x
析构函数                  v

虚析构:主要作用在继承关系中,防止内存泄露,满足同名覆盖  
虚析构函数可以认为是特殊的析构函数,主要作用在继承关系中。
若B是A的子类:  A *a=new B;
                            delete a;
如果A的析构函数是non-vartual,则只会调用A的析构函数,这样B的资源没有释放,就会有内存泄露;
如果A的析构函数是vartual,则只会先调用A的析构函数,再调用B的析构函数。


多态的发生时机:指针调用虚函数、对象完整 
虚表的写入时机:构造函数的第一行代码执行之前、虚表的二次写入
虚继承:virtual函数的继承
继承的内存布局:非虚基类的布局优先于虚基类、虚基类的处理顺序为继承顺序
实现一个不能被继承的类:类似单例模式的处理、和普通类相同的处理、虚继承
友元函数特性:单向性、不可继承、不可传递  

面向对象五大基本原则 
单一职责原则SRP(Single Responsibility Principle)
是指一个类的功能要单一,不能包罗万象。如同一个人一样,分配的工作不能太多,否则一天到晚虽然忙忙碌碌的,但效率却高不起来。
开放封闭原则OCP(Open-Close Principle) 
一个模块在扩展性方面应该是开放的而在更改性方面应该是封闭的。比如:一个网络模块,原来只服务端功能,而现在要加入客户端功能,那么应当在不用修改服务端功能代码的前提下,就能够增加客户端功能的实现代码,这要求在设计之初,就应当将服务端和客户端分开,公共部分抽象出来。
里氏替换原则(the Liskov Substitution Principle LSP) 
子类应当可以替换父类并出现在父类能够出现的任何地方。比如:公司搞年度晚会,所有员工可以参加抽奖,那么不管是老员工还是新员工,也不管是总部员工还是外派员工,都应当可以参加抽奖,否则这公司就不和谐了。
依赖倒置原则(the Dependency Inversion Principle DIP)
具体依赖抽象,上层依赖下层。假设B是较A低的模块,但B需要使用到A的功能,这个时候,B不应当直接使用A中的具体类: 而应当由B定义一抽象接口,并由A来实现这个抽象接口,B只使用这个抽象接口:这样就达到了依赖倒置的目的,B也解除了对A的依赖,反过来是A依赖于B定义的抽象接口。通过上层模块难以避免依赖下层模块,假如B也直接依赖A的实现,那么就可能造成循环依赖。一个常见的问题就是编译A模块时需要直接包含到B模块的cpp文件,而编译B时同样要直接包含到A的cpp文件。
接口分离原则(the Interface Segregation Principle ISP) 
模块间要通过抽象接口隔离开,而不是通过具体的类强耦合起来

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值