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.概述 泛型算法依赖于迭代器,而不是依赖容器,需要指定作用的区间,即[开始,结束),表示的区间,如上所示 此外还需要元素是可比的,如果元素本身是不可比的,那么可以自己定义比较函数 ...
随机推荐
- onkeydown、onkeypress、onkeyup、onblur、onchange、oninput、onpropertychange的区别
onkeydown:按下任何键(字母.数字.系统.tab等)都能触发,且对于字母不区分大小写: onkeypress:按下字母.数字键时触发,且对于字母区分大小写; onkeyup:相应的键和onke ...
- linux中fork()函数详解(搬砖)
一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同, ...
- [Hibernate]Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set
使用Hibernate官方文档上的下面代码进行測试时报出这个异常. org.hibernate.HibernateException: Access to DialectResolutionInfo ...
- MongoDB(一)——简介
这两天简单学习了一下MongoDB数据库,属于NoSQL类型数据库的一种,先简单宏观的看一下NoSQL的相关知识和MongoDB的基础知识. NoSQL是Not Only SQL的缩写,它指的是非关系 ...
- Zorka监控平台的Online reconfiguration基本效果展示
在上一篇日志中,我简介了Zorka的Online reconfiguration的用法,可是没怎么介绍如何看到在线更改的效果,这里简单说说. 还是以之前的tomcat为例,我们在文件夹zorka\sc ...
- 查看typedef类型
typedef unsigned long int NUM; #include <iostream> using namespace std; NUM x; cout << t ...
- Kettle的四大不同环境工具
不多说,直接上干货! kettle里有不同工具,分别用于ETL的不同阶段. 初学者,建议送Spoon开始.高手,是四大工具都会用. Sqoop: 图形界面工具,快速设计和维护复杂的ETL工作流.集成开 ...
- Android View 上下左右四种间距的设置方法
RecyclerView控件大家肯定不陌生,已经应用有一段时间了,最近在项目中写一个GridLayout样式的RecyclerView时需要设置,item之间左右的间距,下面是我总结的一个设置间距的方 ...
- 【原创】关于JMS[1]
面向消息中间件(MOM)为分布式系统提供异步,解耦,稳定,可扩展和安全的行为.MOM在分布式计算领域是一个重要的概念.它允许应用使用代理器API在分布式环境实现各种功能.Java消息服务(Java M ...
- activity的23张表
--二进制数据表 SELECT * FROM act_ge_bytearray; --属性数据表存储整个流程引擎级别的数据,初始化表结构时,会默认插入三条记录, SELECT * FROM act_g ...