1 oop的思想是 数据抽象 继承 和 动态绑定
数据抽象可以将类的接口与实现分离;
继承
动态绑定,又称运行时绑定
2 虚函数是基类希望其派生类进行覆盖的函数
<1> 任何构造函数之外的非静态函数都可以是虚函数
<2> 成员函数若没有被声明为虚函数。则其解析过程发生在编译时而非运行时
<3> 派生类可以访问基类的public和protected成员 ,但是不能访问private成员
3 什么是虚成员?
所谓的虚成员是指用virtual关键字修饰的类的成员函数,他的功能可以在运行时由他的派生类中重定义
4 区分protected 和 private
protected为受保护的访问说明符。
他的成员可以被该类的成员、右元和派生类成员访问。
而private可以被该类的成员、右元访问。派生类不能直接访问
5 派生类必须使用基类的构造函数来初始化它的基类部分
6 如果我们想将某个类用作基类,则基类必须已经定义而非仅仅声明
也代表一个类不能派生自己
7 一般我们只允许将指针或引用绑定到同类型的对象上,但是基类是一个类外,一个基类的指针或引用可以绑定在基类或者其派生类的对象身上。
所以我们可以将一个派生类指针存储在一个基类的智能指针内
8 基类的指针或引用的静态类型可能与其动态类型不一致
静态类型:变量声明时候的类型,在编译阶段就可以确定了
动态类型:指针或者引用所代表的内存中的对象的类型,在运行阶段才可以确定
动态类型是可以发生变化的;并且动态类型的概念是针对指针和引用这两个东西而引出来的。
静态绑定:有人也叫为早绑定,早绑定什么呢?对象所调用的函数的地址,这个阶段是程序编译阶段就确定的了;
动态绑定:有人也叫晚绑定,也就是编译阶段时候不能确定对象调用函数的地址,需要程序运行到调用函数的阶段才可以确定;
绑定:是相对与函数的概念,把对象(包括引用和指针)和函数绑定在一起
如果没有虚函数的话,即使静态类型和动态类型不一样
例如
Base* a = new Deried;
它的静态类型为Base* 动态类型为Deried* 但是仍然是静态绑定 仍然执行的是基类中的成员函数,因为它优先执行的是基类对象中的成员函数,并不会进行重写
但是当有了虚函数之后,他会对基类中的成员函数进行重写,动态绑定子类的成员函数
即:只有虚函数使用的绑定才是动态绑定。
9 从派生类到基类的类型转换只对指针和引用类型有效
10 我们不能定义抽象基类的对象
11 派生类中的成员和友元只能访问派生类对象中的基类部分的受保护成员。对于普通的基类对象中的该成员不具有特殊的访问权限
12
13 右元不能继承,而且需要注意的是对基类的友元,对派生类的基类部分也是可以访问的
14
1.只有当派生类公有地继承基类时,用户代码才能使用派生类向基类的转换。也就是说,如果派生类继承基类的方式是受保护的或者私有的,则用户代码不能使用该转换。
2.无论派生类以什么方式继承基类,派生类的成员函数和友元都能使用派生类向基类的转换;派生类向其直接基类的类型转换对于派生类的成员来说永远是可访问的。
3.如果派生类继承基类的方式是公有的或者受保护的,则派生类的成员和友元可以使用派生类向基类的类型转换;反之,如果派生类继承基类的方式是私有的,则不能使用。
15
16 一般来说,基类需要定义一个虚析构函数。这样我们就能动态分配继承体系中的对象了。
17
<1> 如果我们给一个类 定义了自己的拷贝构造函数、拷贝赋值函数或者析构函数,则移动合成函数是=delete的。如果一个类没有移动操作,这个时候移动对象使用的是合成的拷贝操作。
<2> 只有当一个类没有定义任何自己版本的拷贝控制成员,且它的所有数据成员都能移动构造或者移动赋值时候,编译器才会为他合成移动构造函数或移动赋值运算符。
<3> 定义了一个移动构造函数或移动赋值运算符的类也必须定义自己的拷贝操作,不然默认被定义为删除的
注意:如果类成员是const或者引用,则类的拷贝和移动赋值运算符被定义为删除
18 我们定义了一个类的传参的构造函数,则默认构造函数是删除的,除非被显式的定义 = default
因此,基类的默认构造函数必须显示定义,确保其派生类在执行它的默认构造函数时能调用基类默认构造函数。
标签:基类,函数,成员,绑定,C++,第十五章,派生类,primer,构造函数 From: https://www.cnblogs.com/lihaoxiang/p/17262231.html