1.继承:
在C++语言中,基类将类型相关的函数与派生类不做改变直接继承的函数区分对待。对于
某此函数,基类希望它的派生类个自定义适合自身的版本,此时基类就将这此函数声明成
虚函数(virtual function ) 因此,我们可以将Quote类编写to
class Quote{
public:
std::string isbn()
v工rtual double net
};
const;
price(std::size_t n) const;
派生类必须通过使用类派生列表(class derivation list )确指处它是那个类继承而来的。类派尘列表的形式是:首先是一个’冒号,后而紧跟以逗号分隔的基类列表,
其中每个基类前面可以有访问说说明符:
class Bulk_ quote:public Quote{
public:
double net_price(std::size t) const override ;//Bulk_quote继承了Quote
};
• C++的虚函数主要是为了实现多态。基类定义的虚函数,派生类重新定义该函数,这样基类对象指针调用哪一个函数是判断该基类指针的对象的类型。
• 虚函数用virtual关键字修饰,同时开启动态联编技术,动态联编只有程序运行时才能确定调用的函数,在编译阶段是不知道要调用哪一个函数。
函数的运行版本由实参决定,即在运行时选择函数的版本,所以动态绑定有时候又被称为运行时绑定(run-time binding )
在C++语言中,当我们使用基类的引用(或指针)调用一个虚函数时将发生动态绑定!
2.基类通常都应该定义一个虚析构函数,即使该函数不执行任何实际操作也是如
如此。
3成员函数与继承:
在C.++语言中,基类必须将它的两种成员函数区分开来:一种是基类希望其派生类进
行覆盖的函数:另种是基类直接继承而不要改变的函数。对上前者,基类通常将其定义为虚函数VIRTUAL。我们使用指针或引用调用啦函数时,该调用将被动态绑定。根据引川或指针所绑定的对象类型不同,该调用可能执行基础类的版本,也可能执行某个派生类的版本。
任何构造函数之外的非静态函数都可以是虚函数,关键字virtual 只能出现在类内部的声明语句之前而不能定义在类外部的函数定义。如果基类被定义为虚函数那么!他的派生类也隐示为虚函数!
4.在派生类对象中含有与其基类对应的组成部分,这一事实是继承的关键所在。
5.每个类控制它自己的成员初始化过程。
6.继承与静态成员:
如果基类定义了一个静态成员则在整个继承体系,只存在该成员的唯一定义。不沦从基类,派生出来多少个派生类,对于每个静态成员来说都只存在准一的‘实例。
Class Base{
Public:
static void statmem();
};
Class Der:public Base{
void f(const Der);
}
静态成员遵循通用的访问于控制规则,如果基类中的成员是private的.则派生类无权访问
问它。假设某静态成员是可访问的,则我们既能通过堪类使用他也能通过派生类使用它:
7.和内置指针一样,智能指针类也支持派生类向基类的类型转换,这意味着我们可以将一个派生类对象的指针存储在一个基类的智能指针内。
8.存在继承关系的类型之间的转换规则:
要想理解在具有继承关系的类之间发生的类型转换,有三点非常重要:
• 从派生类向基类的类型转换只对指针或引用类型有效
• 墓类向派生类不存在隐式类型转换。
• 和任何其他成员一样,派生类向基类的类型转换也可能会由于访问受限而变得不 可行。
尽管自动类型转换只对指针或引用类型有效,但是继承体系中的大多数类仍然(显式或
隐式地)定义了拷贝控制成员因此,我们通常能够将一个派生类对象拷贝、移动或赋值给一个基类对象不过需要注意的是,这种操作只处理派生类对象的
基类部分。
9.C++多态性
OOP的核心思想是多态性(polymorphism)多态性这个词源自希腊语,其含义是
“多种形式”我们把具有继承关系的多个类型称为多态类型,因为我们能使用这些类型
的“多种形式”而无须在意它们的差异。引用或指针的静态类型与动态类型不同这一事
实正是C++语言支持多态性的根本所在。
当我们使用基类的引用或指针调基类中定义的一个函数时,我们并不知道该函数
真正作用的对象是什么类型,因为它可能是一个基类的对象也可能是一个派生类的对
象。如果该函数是虚函数,则直到运行时才会决定到底执行哪个版本,判断的依据是引
用或指针所绑定的对象的真实类型。
另一方面,对非虚函数的调用在编译时进行绑定。类似的,通过对象进行的函数(虚
函数或非虚函数)调用也在编译时绑定对象的类型是确定不变的,我们无论如何都不
可能令对象的动态类型与静态类型不一致。因此,通过对象进行的函数调用将在编译时
绑定到该对象所属类中的函数版本上。
当且仅当对通过指针或引用调用虚函数时,才会在运行时解析该调用,也只有
在这种情况下时象的动态类型才有可能与静态类型不同
10.名字查找与继承
理解函数调用的解析过程刘一于理解C++-的继承至关重要,假定我们调用p一>mem ( )
(或者obj . mem ( )),则依次执行以下4个步骤:
• 首先确定p(或obj)的静态类型因为我们调用的是一个成员,所以该类型必
然是类类型。
• 在p(或。bj)的静态类型对应的类中查找mem如果找不到,则依次在直接基
类中不断查找直至到达继承链的顶端如果找遍了该类及其基类仍然找不到,则编译器
将报错。
• 一旦找到了mem,就进行常规的类型检查(参见6.1节,第183页)以确认对于
当前找到的mem,本次调用是否合法。
• 假设调用合法,则编译器将根据调用的是否是虚函数而产生不同的代码:
一如果mem是虚函数且我们是通过引用或指针进行的调用,则编译器产生的代
码将在运行时确定到底运行该虚函数的哪个版本,依据是对象的动态类型。
一反之,如果mem不是虚函数或者我们是通过对象(而非引用或指针)进行的
调用,则编译器将产生一个常规函数调用。
网友评论