C++编程思想(2nd卷一):多态性和虚函数
2009-11-09 09:19
141 查看
当捆绑在程序运行之前完成时,这称为早捆绑(early binding)。
捆绑根据对象的类型,发生在运行时,称为晚捆绑(late binding)。晚捆绑又称为动态捆绑或运行时捆绑。
在派生类中virtual函数的重定义通常称为重写(overriding)。
使用虚函数类的长度:
带有单个虚函数的类,对象的长度是未带虚函数类的长度加上一个void指针的长度。
如果有一个或多个虚函数,编译器都只在这个结构中插入一个单个指针(VPTR)。因此带一个或两个虚函数的类长度是没有区别的。这是因为VPTR指向一个存放函数地址的表。我们只需一个表,因为所有虚函数地址都包含在这个单个表中。
每当创建一个包含有虚函数的类或从包含有虚函数的类派生一个类时, 编译器就为这个类创建一个唯一的VTABLE。
当继承一个抽象类时,必须实现所有的纯虚函数,否则继承出的类也将是一个抽象类。创建一个纯虚函数允许在接口中放置成员函数,而不一定要提供一段可能对这个函数毫无意义的代码。同时,纯虚函数要求继承出的类对它提供一个定义。
建立公共接口的唯一原因是它能对于每个不同的子类有不同的表示。
纯虚函数禁止对抽象类的函数以传值方式调用,通过抽象类,可以保证在向上类型转换期间总是使用指针或引用。
纯虚定义:在抽象类的外部对其纯虚函数定义,可达到对纯虚函数定义的效果。另一个好处是这样允许我们实现从常规虚函数到纯虚函数的改变,而无需打乱已存在的代码。
对象切片实际上是当它拷贝到一个新的对象时,去掉原来对象的一部分,而不是像使用指针或引用那样简单地改变地址的内容。因此,不常使用对象向上类型转换,事实上,通常要提防或防止这种操作。
编译器不允许我们在派生类中改变基类中已定义过的虚函数的返回值。如果重新定义了基类中的一个重载成员函数,则在派生类中其他的重载函数将会被隐藏。
对于在构造函数中调用一个虚函数的情况,被调用的知识一个函数的本地版本,也就是说,虚机制在构造函数中不工作。在构造函数中调用虚函数都不能得到预期的结果。
构造函数是不能为虚函数的。但析构函数能够且常常必须是虚的。
作为一个准则,任何时候我们的类中都要有一个虚函数,我们应当立即增加一个虚析构函数。这样,我们保证在后面不会出现问题。
在析构函数中,只有成员函数的本地版本被调用,虚机制被忽略。
编译器决定在编译时只调用当前函数的“本地”版本的两个情况:
构造函数的情况下:因为类型信息还不可用,被调用的函数可能操作还没有被初始化的成员。
析构函数的情况下:因为信息(VPTR)虽存在,但不可靠,被调用的函数就可能操作在已被删除的对象上。
捆绑根据对象的类型,发生在运行时,称为晚捆绑(late binding)。晚捆绑又称为动态捆绑或运行时捆绑。
在派生类中virtual函数的重定义通常称为重写(overriding)。
使用虚函数类的长度:
带有单个虚函数的类,对象的长度是未带虚函数类的长度加上一个void指针的长度。
如果有一个或多个虚函数,编译器都只在这个结构中插入一个单个指针(VPTR)。因此带一个或两个虚函数的类长度是没有区别的。这是因为VPTR指向一个存放函数地址的表。我们只需一个表,因为所有虚函数地址都包含在这个单个表中。
每当创建一个包含有虚函数的类或从包含有虚函数的类派生一个类时, 编译器就为这个类创建一个唯一的VTABLE。
当继承一个抽象类时,必须实现所有的纯虚函数,否则继承出的类也将是一个抽象类。创建一个纯虚函数允许在接口中放置成员函数,而不一定要提供一段可能对这个函数毫无意义的代码。同时,纯虚函数要求继承出的类对它提供一个定义。
建立公共接口的唯一原因是它能对于每个不同的子类有不同的表示。
纯虚函数禁止对抽象类的函数以传值方式调用,通过抽象类,可以保证在向上类型转换期间总是使用指针或引用。
纯虚定义:在抽象类的外部对其纯虚函数定义,可达到对纯虚函数定义的效果。另一个好处是这样允许我们实现从常规虚函数到纯虚函数的改变,而无需打乱已存在的代码。
对象切片实际上是当它拷贝到一个新的对象时,去掉原来对象的一部分,而不是像使用指针或引用那样简单地改变地址的内容。因此,不常使用对象向上类型转换,事实上,通常要提防或防止这种操作。
编译器不允许我们在派生类中改变基类中已定义过的虚函数的返回值。如果重新定义了基类中的一个重载成员函数,则在派生类中其他的重载函数将会被隐藏。
对于在构造函数中调用一个虚函数的情况,被调用的知识一个函数的本地版本,也就是说,虚机制在构造函数中不工作。在构造函数中调用虚函数都不能得到预期的结果。
构造函数是不能为虚函数的。但析构函数能够且常常必须是虚的。
作为一个准则,任何时候我们的类中都要有一个虚函数,我们应当立即增加一个虚析构函数。这样,我们保证在后面不会出现问题。
在析构函数中,只有成员函数的本地版本被调用,虚机制被忽略。
编译器决定在编译时只调用当前函数的“本地”版本的两个情况:
构造函数的情况下:因为类型信息还不可用,被调用的函数可能操作还没有被初始化的成员。
析构函数的情况下:因为信息(VPTR)虽存在,但不可靠,被调用的函数就可能操作在已被删除的对象上。
相关文章推荐
- C++编程思想(2nd卷一):多态性和虚函数
- C++笔记——c++编程思想(上)多态性、虚函数与模板
- C++编程思想杂记(15章 多态性和虚函数)
- C++编程思想(2nd卷一):运算符重载
- C++编程入门系列之四十八(多态性:虚函数)
- C++编程思想(2nd卷一):动态对象创建
- C++编程思想(2nd卷一):继承和组合
- C++编程思想(2nd卷一):内联函数
- C++编程思想(2nd卷一):函数重载与默认参数
- C++编程思想(2nd卷一):名字控制
- C++编程思想(2nd卷一):引用和拷贝构造函数
- C++编程思想(2nd卷一):常量
- C++编程思想(2nd卷一):模板简介
- C++编程思想(2nd卷一):函数重载与默认参数
- C++编程思想(2nd卷一):运算符重载
- C++编程思想(2nd卷一):内联函数
- C++编程思想(2nd卷一):常量
- C++编程思想(2nd卷一):动态对象创建
- C++编程思想(2nd卷一):名字控制
- C++编程思想(2nd卷一):继承和组合