1. 多态性的概述

1.1 多态是指同样的消息被不同类型的对象接收时导致不同的行为。所谓消息是指对垒的成员函数的调用,不同行为是指不同的实现。

1.2 多态的实现

  (1) 实现角度讲多态可分为两类:编译时的多态和运行时的多态。

    ① 编译时:编译过程中确定了同名操作的具体操作对象。静态绑定。

    ② 运行时:程序运行时动态确定操作针对的具体对象。动态绑定。

2. 运算符重载

2.1 运算符重载就是对已有的运算符赋予多重含义,使同一个运算符作用域不同类型的数据导致不同的行为。

2.2 运算符重载的实质是函数重载。在实现过程中,首先把制定的运算表达式转化为对运算符函数的调用,然后把运算对象转化为运算符函数的实参,然后根据实参类型确定调用的函数,这个过程是在编译过程完成的。

2.3 运算符重载的规则

  (1) 只能重载C++中已经有的运算符

  (2) 重载之后的优先级和结合型不变

  (3) 运算符重载是针对新类型数据的实际需要,对原有运算符进行适当的改造。因此重载后的功能因该与原功能类似,不能改变操作对象个数,同时至少有一个操作对象是自定义类型

2.4 运算符重载的形式:重载为类的非静态成员函数和重载为类的成员函数

  (1) 重载为类的成员函数

    返回类型 operator 运算符(形参表)

    {}

  (2) 重载为非成员函数。此时有可能需要将此函数声明为友元函数。

    返回类型 operator 运算符(形参表){

    }

2.5 运算符重载为成员函数

  (1) 双目运算符

    左操作数是对象本身数据,由this指针指出,有操作数是通过重载函数的参数表实现

    双目运算符B。 为了实现 oprd1 B oprd2。 应该把B实现为oprd1的重载运算符函数,该函数有一个形参,类型是oprd2对应的类型。重载后,oprd1 B   oprd2即为 oprd1.operator B(oprd2)

    例子:  

Complex operator+ (const Complex &c2) const;
Complex Complex::operator+ (const Complex &c2) const{
reuturn ...;
}

  (2) 前置单目运算符

    操作数由对象的this指针指出,无需参数

    比如’-‘等运算符U, U oprd.应该重载为oprd类型的成员函数,没有形参。表达式 U oprd即为 oprd.U()

    例子:

Clock& operator++();
Clock& Clock::opertor++(){
reutrn ..;
}

  (3) 后置单目运算符

    操作数由对象的this指针指出。

    比如++和--,此时,运算符应重载为对象的成员函数,这个函数有一个int 的形参,这个参数没有用处,只是为了区分前置和后置

    例子:

Clock operator++(int);
Clock Clock::operator++(int)
{
return ...;
}

2.6 运算符重载为非成员函数

  (1) 对于双目运算符B,如果要实现oprd1 B oprd2,其中oprd1和oprd2中只要有一个具有自定义类型,就可以将B重载为非成员函数,函数的形参oprd1 和 oprd2。经过重载后oprd1 B oprd2 就相当于函数调用operator B(oprd1, oprd2)

  (2) 其他的类似,就是多个参数

  (3) 例子:

class Complex{
public:
friend Complex operator+( const Complex &c1, const Complex &c2);
friend Complex ostream & operator<<( ostream &out, const Complex &c);
private:
...
} Complex operator+(const Complex &c1, const Complex &c2){
return Complex(c1.real + c2.real, c1.imag + c2.imag);
} ostream & operator<<(ostream &out, const Complex &c)
{
out<<c.imag;
return out;
}

3. 虚函数

3.1 虚函数是动态绑定的基础。虚函数必须是非静态的成员函数。虚函数经过派生后就可以实现运行过程中的多态。

3.2 如果需要通过基类的指针指向派生类的对象,并且访问某个与基类同名的成员,那么首先在基类中将这个同名函数声明为虚函数。

3.3 一般虚函数成员

  (1) 声明语法:

    virtual 函数类型 函数名(形参表)

  (2) 虚函数声明只能出现在类定义中的函数原型声明中,而不能在成员函数实现的时候。

  (3) 如果基类声明了虚函数,而派生类相应函数没有声明virtual,那么系统根据如下规则:

    ① 该函数是否与基类的虚函数有相同名称

    ② 该函数是否与基类的虚函数有相同的参数

    ③ 该函数是否与基类的虚函数有相同的返回值或者满足复制兼容规则的指针、引用型的返回值

  (4) 只有虚函数是动态绑定的,如果派生类需要修改基类的行为(即重写与基类函数同名的函数),就应该在基类中将相应的函数声明为虚函数。而基类中声明  的非虚函数,通常代表那些不希望被派生类改变的功能,也是不能实现多态的。一般不要重写继承而来的非虚函数,那会导致通过基类指针和派生类指针或者对  象调用同名函数时产生不同的后果,从而引起混乱。

3.4 虚析构函数

  (1) 如果基类声明为虚析构函数,则派生类的构造函数也为虚函数。

  (2) 如果需要用基类的指针调用派生类的析构函数则一定要声明虚析构函数。

4. 纯虚函数与抽象类

  建立抽象类就是为了通过多态使用成员函数。抽象类自身无法实例化,只能通过继承机制,生成非抽象派生类,再进行实例化。

4.1 纯虚函数

  (1) 纯虚函数是一个在基类中声明的虚函数,在基类中没有定义具体的操作,要求各派生类根据实际需要给出自己的定义。

  (2) 声明格式:

    virtual 函数类型函数名(参数表)= 0;//后面的 = 0

  (3) 声明为虚函数后,基类中就可以不再给出函数的实现部分。

  (4) 如果将析构函数声明为纯虚函数,则必须在基类中给出它的实现,因为派生类的析构函数执行完后需要调用基类的析构函数。实际上,基类中是可以给出纯  虚函数的函数体,但是即使给出,也必须由派生类覆盖。

4.2 抽象类

  (1) 带有纯虚函数的类是抽象类。抽象类的主要作用是通过它为一个类族建立一个公共接口。

  (2) 抽象类派生出新的类后,如果派生类给出所有纯虚函数的函数实现,这个派生类就可以定义自己的对象。

  (3) 抽象类不能实例化。

作者:viczzx 出处:http://www.cnblogs.com/zixuan-zhang 欢迎转载,也请保留这段声明。谢谢!

C/C++基础知识总结——多态性的更多相关文章

  1. java基础知识小总结【转】

    java基础知识小总结 在一个独立的原始程序里,只能有一个 public 类,却可以有许多 non-public 类.此外,若是在一个 Java 程序中没有一个类是 public,那么该 Java 程 ...

  2. 基础知识系列☞Abstract和Virtual→及相关知识

    转载地址→http://www.cnblogs.com/blsong/archive/2010/08/12/1798064.html 在C#的学习中,容易混淆virtual方法和abstract方法的 ...

  3. JAVA面试题集之基础知识

                           JAVA面试题集之基础知识 基础知识:  1.C 或Java中的异常处理机制的简单原理和应用. 当JAVA程序违反了JAVA的语义规则时,JAVA虚拟机就 ...

  4. Java 基础知识总结

    作者QQ:1095737364    QQ群:123300273     欢迎加入! 1.数据类型:  数据类型:1>.基本数据类型:1).数值型: 1}.整型类型(byte  8位   (by ...

  5. Java基础知识二次学习--第三章 面向对象

    第三章 面向对象   时间:2017年4月24日17:51:37~2017年4月25日13:52:34 章节:03章_01节 03章_02节 视频长度:30:11 + 21:44 内容:面向对象设计思 ...

  6. Java基础知识回顾之七 ----- 总结篇

    前言 在之前Java基础知识回顾中,我们回顾了基础数据类型.修饰符和String.三大特性.集合.多线程和IO.本篇文章则对之前学过的知识进行总结.除了简单的复习之外,还会增加一些相应的理解. 基础数 ...

  7. Java基础知识总结(超级经典)

    Java基础知识总结(超级经典) 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部分用到哪些语句,方法,和对象. 4,代码实现.用具体的java ...

  8. C#基础知识之面向对象以及面向对象的三大特性

    在C#基础知识之类和结构体中我详细记录了类.类成员.重载.重写.继承等知识总结.这里就记录一下对面向对象和面向对象三大特性的广义理解. 一.理解面向对象 类是面向对象编程的基本单元,面向对象思想其实就 ...

  9. 毕向东—Java基础知识总结(超级经典)

    Java基础知识总结(超级经典) 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部分用到哪些语句,方法,和对象. 4,代码实现.用具体的java ...

随机推荐

  1. [Unity3D]Unity3D游戏开发MatchTarget的作用攀登效果实现

    大家好,我是秦培,欢迎关注我的博客.我的博客地址blog.csdn.net/qinyuanpei. 今天我们来一起学习在Unity3D中怎样实现角色攀爬效果. 在RPG游戏中,某些游戏场景经常须要玩家 ...

  2. oracle_表分区

    一. 分区表理论知识 Oracle提供了分区技术以支持VLDB(Very Large DataBase).分区表通过对分区列的判断,把分区列不同的记录,放到不同的分区中.分区完全对应用透明. Orac ...

  3. Java高效编程(2) -- Creating and Destroying Objects

    Item 1: Consider static factory methods instead of constructors Advantage: One advantage of static f ...

  4. input的width和padding-left同时存在时IE兼容问题

    总的来说,text-indent不影响元素的最终宽度但是有兼容性问题,padding-left在中国主流浏览器IE低版本下影响最终宽度,但在chrome和firefox下不影响宽度,但是可以通过CSS ...

  5. 经常使用git命令集

    //创建本地仓库 mkdir git_root;cd git_root;git init // //查看 git status . git log git log ./kernel/driver/ g ...

  6. 如何使用Ubuntu online account API创建微博HTML5申请书

    在这篇文章中.我们将使用Ubuntu SDK提供online account API来訪问微博的API并显示所须要的内容.这篇文章的重点是展示怎样在HTML 5中使用online account AP ...

  7. 10. IDENTITY属性使用小结

    原文:10. IDENTITY属性使用小结 从SQL Server 2012开始有了Sequence,简单用列如下: CREATE SEQUENCE TestSeq START INCREMENT ; ...

  8. (转)迎接 Entity Framework 7

    对实体框架的下一版本的开发正在顺利进行中.我在 2014 年度北美 TechEd 上第一次了解 EF 团队的工作内容,当时项目经理 Rowan Miller 讨论了 Entity Framework ...

  9. Java获取系统相关信息System.getProperty()

    java.version Java 运行时环境版本 java.vendor Java 运行时环境供应商 java.vendor.url Java 供应商的 URL java.home Java 安装目 ...

  10. .NET到Node.js

    从.NET到Node.js谈前后端分离实践(by vczero)   一.最初的[无分离]实践 11年末的时候,用winForm开发程序,拖拖控件,点点按钮,连接数据库,做一些基本的管理系统:Java ...