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. erlang R17新socket选项{active,N}

    erlang R17带来了新的socket选项{active,N} .与{active,once}连同应用层提供的流量控制.为什么会这样选择,{active,once}不能够有效地抑制了很多socke ...

  2. Same binary weight (位运算)

    题目描述 The binary weight of a positive  integer is the number of 1's in its binary representation.for ...

  3. hdu 4915 Parenthese sequence(模拟)2014多培训学校5现场

    Parenthese sequence                                                                     Time Limit: ...

  4. UITableView Cell 弹簧动画效果

    - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath ...

  5. 有关doctype!!!

    浏览器呈现模式 现代浏览器包括不同的呈现模式,目的是既支持遵循标准的网页,也支持为老式浏览器而设计的网页.其中, Standards (标准)模式(也就是严格呈现模式)用于呈现遵循最新标准的网页,而 ...

  6. WCF与Web API 区别

    WCF与Web API 区别(应用场景)   Web api  主要功能: 支持基于Http verb (GET, POST, PUT, DELETE)的CRUD (create, retrieve, ...

  7. W5500问题集锦(一)

    在"WIZnet杯"以太网技术竞赛中,有非常多參赛者在使用中对W5500有各种各样的疑问,对于这款WIZnet新推出的以太网芯片,使用中大家是不是也一样存在下面问题呢?来看一看: ...

  8. 用CQRS+ES实现DDD

    用CQRS+ES实现DDD 这篇文章应该算是对前三篇的一个补充,在写之前说个题外话,有园友评论这是在用三层架构在写DDD,我的个人理解DDD是一种设计思想,跟具体用什么架构应该没有什么关系,DDD也需 ...

  9. style、currentStyle、getComputeStylel的使用

    (1)js中使用obj.style的用法,是为了获得内联样式,即style属性中的值. 如果想获取obj.style.display,但内联样式表中没有定义display,那么将返回一个空的字符串. ...

  10. jQuery EasyUI API - Base - Draggable [原创汉化官方API]

    最近在学习jQuery EasyUI,发现中文的文档好少,部分文档不错但它是鸟语的,为了大家也为了自己学习吧,汉化做一下笔记. 有没有说清楚的,或者翻译不正确的地方还请大家谅解指出.. 由于工作时间原 ...