C++primer读书笔记11-多态
多态也是C++中的一个重要的方面。多态和动态类型,虚函数本质上是指同样的事情。
1 虚函数
类中的成员函数原型前面加上virtual 表面这个函数是个虚函数。虚函数的目的是为了在继承它的派生类中又一次定义这个函数,以便于通过基类的指针或引用在执行时对派生类的函数进行调用。
2 派生类和虚函数
派生类普通情况下要重定义所继承的虚函数。有几个注意事项。
<1>虚函数的声明必须和基类中的函数声明原型全然一致。例外的是当基类返回基类型的指针或者引用的时候。派生类能够派生类类型的指针或者引用
<2>virtual 关键词加不加无所谓,可是一般要加上,能看的清楚这是个虚函数
<3>virtual的标签一旦在基类中的函数前面加上。就永远也去不掉
3 动态绑定的触发
C++的函数调用默认不使用动态绑定。使用动态绑定须要两个必须的条件
<1>通过基类类型的指针或者引用进行函数的调用
<2>函数是虚函数
通过这里也能够说明,当通过指针或者引用调用函数的时候,即便派生类重定义了基类的版本号。也不会调用派生类的版本号。由于它不会触发多态。
4 虚函数的覆盖机制
有时候通过指针或者引用不想触发多态。此时能够通过加限定符来显式的调用基类的函数
Derived d;
Base *p = &d;
p->Base::func();
假设在派生类中的函数定义的时候想要调用基类的同名函数那么也要这样显式的调用,否则会引发无穷递归。
5 虚函数跟复制控制
<1>通常将析构函数设置为虚函数,这是由于析构函数在运行的时候仅仅会运行自身的部分。
比如通过基类的指针或者引用来调用析构函数的话,那么仅仅会调用基类的构造函数。派生类的构造函数将不会被调用。
<2>构造函数不能定义为虚函数,由于在构造函数是在对象全然构造之前执行的。在构造函数执行的时候,对象的动态类型还不完整。
<3>赋值操作符原理上能够设置为虚函数。可是这样做是没意义的。原因例如以下:
虚函数要求函数原型全然一致,这当中包含了函数參数类型的一致,假设我们把operator = 设置为虚函数。那么在基类中函数的參数是基类类型,在派生类虚函数的參数类型依旧是基类类型。可是赋值操作符是要求函数參数类型和类类型一致。这样就会产生很easy混淆的东西。
class Base{
public:
virtual Base& operator =(Base& xx);
}
class Derived : public Base
{
public:
virtual Derived& operator =(Base& xx); //virtual function
Derived& operator =(Derived& xx); //real operator =
}
6 构造函数和析构函数中的虚函数
在执行构造函数和析构函数的时候。此时的对象都不是一个完整的类。这个时候编译器将对象的对象视作在构造期间发生了变化,假设在当中调用虚函数的话。那么调用的将会是类自身类型
定义的版本号。
原因:基类在构造的时候,派生类部分的成员还没有初始化,假设此时调用的是派生类的虚函数,那么派生类的虚函数訪问类成员就会出问题。
同理基类的析构函数也是这样子。由于析构函
数直管自身成员的释放,派生类在调用析构函数的时候先调用自身的析构函数。然后再去调用基类的析构函数。所以基类的析构函数不可能调用派生类的虚函数,由于派生类的成员已经被释
放。实比例如以下:
//Base.h
#pragma once
#include <iostream>
using namespace std; class Base
{
public:
Base(void){ func();};
~Base(void){ funp();};
virtual void func(){cout<<"this is in Base constructor"<<endl;}
virtual void funp(){cout<<"this is in Base destructor"<<endl;};
};
//Derived.h
#pragma once
#include "base.h"
class Derived :
public Base
{
public:
Derived(void){func();}
~Derived(void){func();}
virtual void func(){cout<<"this is in Derived constructor"<<endl;}
virtual void funp(){cout<<"this is in Derived destructor"<<endl;};
};
//main.cpp
#include "Derived.h" void main()
{
Base X;
Derived Y;
}
7 纯虚函数
虚函数的形參后面跟上“=0”则表示纯虚函数。纯虚函数须要注意的有下面几点:
<1>纯虚函数没有函数体;
<2>最后面的“=0”并不表示函数返回值为0,它仅仅起形式上的作用。告诉编译系统“这是纯虚函数”;
<3>这是一个声明语句,最后应有分号。
<4>函数不能被调用
<5>不能创建有纯虚函数的类对象
<6>假设在一个类中声明了纯虚函数,而在其派生类中没有对该函数定义。则该虚函数在派生类中仍然为纯虚函数。
含有一个或者多个纯虚函数的类被称为抽象类。抽象类不能创建对象。抽象类的意义在于提供功能基础接口。然后由派生类来实现,在此基础上实现多态。可是抽象类能够作为引用或者指针。
实例程序例如以下:
//Base.h
#pragma once
#include <iostream>
using namespace std; class Base
{
public:
Base(void){ func();};
~Base(void){ funp();};
virtual void func(){cout<<"this is in Base constructor"<<endl;}
virtual void funp(){cout<<"this is in Base destructor"<<endl;};
virtual void fuck()=0;
};
//Derived.h
#pragma once
#include "base.h"
class Derived :
public Base
{
public:
Derived(void){func();}
~Derived(void){func();}
virtual void func(){cout<<"this is in Derived constructor"<<endl;}
virtual void funp(){cout<<"this is in Derived destructor"<<endl;};
virtual void fuck(){cout<<"what a fuck day it is!"<<endl;}
};
//main.cpp
#include "Derived.h" void main()
{
Derived Y;
Base& X = Y;
}
C++primer读书笔记11-多态的更多相关文章
- 机器学习实战 - 读书笔记(11) - 使用Apriori算法进行关联分析
前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第11章 - 使用Apriori算法进行关联分析. 基本概念 关联分析(associat ...
- 强化学习读书笔记 - 11 - off-policy的近似方法
强化学习读书笔记 - 11 - off-policy的近似方法 学习笔记: Reinforcement Learning: An Introduction, Richard S. Sutton and ...
- Key Technologies Primer 读书笔记,翻译 --- Struct 学习 1
原文链接:https://struts.apache.org/primer.html 本来想写成读书笔记的,结果还是变成翻译,谨作记录,学习. 1.HTML -- 见我前面文章 2.Interne ...
- 《精通Spring 4.X企业应用开发实战》读书笔记1-1(IoC容器和Bean)
很长一段时间关注在Java Web开发的方向上,提及到Jave Web开发就绕不开Spring全家桶系列,使用面向百度,谷歌的编程方法能够完成大部分的工作.但是这种不系统的了解总觉得自己的知识有所欠缺 ...
- c++ primer 读书笔记
顺序容器:为程序提供控制元素存储和访问顺序的能力,这种顺序与元素加入到容器时的位置相对应,而与元素值无关. 另外还有根据关键字的值来存储元素的容器:有序.无序关联容器. 另外STL还有三种容器适配器, ...
- c++ primer读书笔记之c++11(四)
1 带有作用域的枚举 scoped-enumeration 相信大家都用过枚举量,都是不带有作用域的,在头文件中定义需要特别注意不要出现重名的情况.为了解决这种问题,c++11提供了带作用于的枚举. ...
- c++ primer读书笔记之c++11(三)
1 =default构造函数限定符 c++11针对构造函数提供了=default限定符,可以用于显式指定编译器自动生成特定的构造函数.析构或赋值运算函数.参考代码如下: class CtorDftTy ...
- c++ primer读书笔记之c++11(二)
1 新的STL模板类型,std::initializer_list<T> c++11添加了initializer_list模板类型,用于提供参数是同类型情况的可变长度的参数传递机制,头文件 ...
- c++ primer读书笔记之c++11(一)
1 新的关键词nullptr c++11引入新的关键词nullptr,用于表示空指针,用于替换之前c提供的NULL(最初NULL是定义在stdlib中的宏定义,通常是0). 2 新的别名定义机制 al ...
- C++ Primer 读书笔记:第11章 泛型算法
第11章 泛型算法 1.概述 泛型算法依赖于迭代器,而不是依赖容器,需要指定作用的区间,即[开始,结束),表示的区间,如上所示 此外还需要元素是可比的,如果元素本身是不可比的,那么可以自己定义比较函数 ...
随机推荐
- Mysql学习总结(30)——MySQL 索引详解大全
什么是索引? 1.索引 索引是表的目录,在查找内容之前可以先在目录中查找索引位置,以此快速定位查询数据.对于索引,会保存在额外的文件中. 索引,是数据库中专门用于帮助用户快速查询数据的一种数据结构.类 ...
- Opencv 视频转为图像序列
本系列文章由 @YhL_Leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/50283303 基于OpenCV的视频转 ...
- ZOJ 2705
这题,找找规律,可以发现一个斐波那契数列.按照斐波那契数列求和,知道, SUM=Fn+2-F1,于是,该长度为Fn+2的倍数.因为斐波那契数列不一定是从1开始的,而从2开始的每个数都是从1开始的倍数. ...
- 百度分页效果之纯jsp版
数据库连接工具类 package com.gao.page.utils; import java.sql.Connection; import java.sql.DriverManager; publ ...
- sizeof()函数的使用——————【Badboy】
1.sizeof的使用:sizeof操作符以字节形式给出了其操作数的存储大小. sizeof操作符不能用于函数类型,不全然类型或位字段.不全然类型指具有未知存储大小的数据类型,如未知存储大小的数组类型 ...
- MyLayer MyScene
//MyLayer.h #include "cocos2d.h" USING_NS_CC; class MyLayer : public CCLayer { public: sta ...
- Android官方培训课程中文版(v0.9.7)
Android官方培训课程中文版(v0.9.7) Google Android团队在2012年的时候开设了Android Training板块 - http://developer.android.c ...
- 如何在SQLServer中处理每天四亿三千万记录的
项目背景 这是给某数据中心做的一个项目,项目难度之大令人发指,这个项目真正的让我感觉到了,商场如战场,而我只是其中的一个小兵,太多的战术,太多的高层之间的较量,太多的内幕了.具体这个项目的情况,我有空 ...
- DotNetCore.1.0.1-VS2015Tools.Preview2.0.3 相关问题及解决办法
本月16号,MS发布了 .NET Core 1.1.作为一个用贯MS产品的小盆友,我第一时间就把相关的安装包下载下来了,然后果断安装(入坑). 我猜你来看这篇博客可能遇到了和我一样的问题. 问题0:正 ...
- input[type="file"]的图片预览
在项目中遇到用input标签file类型的文件上传,想实在上传之前进行图片的预览功能:之前的做的一个解决方案是文件先上传上去然后返回地址再显示在页面上,这样就不太好,因为用户基本信息可能并没有保存,但 ...