实现C++虚函数时相关注意事宜

开发 后端
C++虚函数是C++语言程序的主要组成部分,一个函数可以调用其他函数。在设计良好的程序中,每个函数都有特定的目的。

C++中的C++虚函数的作用主要是实现了多态的机制,虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的,简称为V-Table,供大家学习参考!

如果一个类不包含虚函数,这经常预示不打算将它作为基类使用。当一个类不打算作为基类时,将析构函数声明为虚拟通常是个坏主意。考虑一个表现二维空间中的点的类:

  1. class Point { // a 2D point  
  2.  public:  
  3.   Point(int xCoord, int yCoord);  
  4.   ~Point();  
  5.  private:  
  6.   int x, y;  
  7. };  

如果一个 int 占 32 位,一个 Point 对象正好适用于 64 位的寄存器。而且,这样一个 Point 对象可以被作为一个 64 位的量传递给其它语言写的函数,比如 C 或者 FORTRAN。如果 Point 的析构函数是虚拟的,情况就完全不一样了。

C++虚函数的实现要求对象携带额外的信息,这些信息用于在运行时确定该对象应该调用哪一个虚函数。典型情况下,这一信息具有一种被称为 vptr(virtual table pointer,虚函数表指针)的指针的形式。

vptr 指向一个被称为 vtbl(virtual table,虚函数表)的函数指针数组,每一个包含C++虚函数的类都关联到 vtbl。当一个对象调用了虚函数,实际的被调用函数通过下面的步骤确定:找到对象的 vptr 指向的 vtbl,然后在 vtbl 中寻找合适的函数指针。

虚函数如何被实现的细节是不重要的。重要的是如果 Point 类包含一个虚函数,这个类型的对象的大小就会增加。在一个 32 位架构中,它们将从 64 位(相当于两个 int)长到 96 位(两个 int 加上 vptr);

在一个 64 位架构中,他们可能从 64 位长到 128 位,因为在这样的架构中指针的大小是 64 位的。为 Point 加上 vptr 将会使它的大小增长 50-100%!Point 对象不再适合 64 位寄存器。而且,Point 对象在 C++ 和其他语言(比如 C)中。

看起来不再具有相同的结构,因为其它语言缺乏 vptr 的对应物。结果,Points 不再可能传入其它语言写成的函数或从其中传出,除非你为 vptr 做出明确的对应,而这是它自己的实现细节并因此失去可移植性。

这里的基准就是不加选择地将所有析构函数声明为虚拟,和从不把它们声明为虚拟一样是错误的。实际上,很多人总结过这条规则:当且仅当类中至少包含一个虚拟函数时,则声明一个虚析构函数。

但是,当完全没有C++虚函数时,就可能和非虚析构函数问题发生撕咬。例如,标准 string 类型不包含C++虚函数,但是被误导的程序员有时将它当作基类使用:

  1. SpecialString *pss = new SpecialString("Impending Doom");  
  2.  
  3. std::string *ps;  
  4. ...  
  5. ps = pss; // SpecialString* => std::string*  
  6. ...  
  7. delete ps; // undefined! In practice,  
  8. // *ps’s SpecialString resources  
  9. // will be leaked, because the  
  10. // SpecialString destructor won’t  
  11. // be called.  

一眼看上去,这可能无伤大雅,但是,如果在程序的某个地方因为某种原因,你将一个指向 SpecialString 的指针转型为一个指向 string 的指针,然后你将 delete 施加于这个 string 指针,你就立刻被送入未定义行为的领地。

【编辑推荐】

  1. C与C++中标准输入实现方式上的一点区别
  2. C++编译器如何对Const常量进行分配存储空间
  3. C++类库设计的基本构思与方法
  4. 玩转C++语言的几种方法
  5. 如何更好的进行C++代码编制
责任编辑:chenqingxiang 来源: 人民邮电出版社
相关推荐

2010-01-28 11:24:14

C++函数

2010-02-01 17:01:16

初学Python

2010-01-22 14:12:40

C++

2010-02-01 13:41:43

2010-01-28 16:42:29

C++静态成员

2009-12-21 17:39:02

ADO.NET操作

2010-01-18 17:38:54

C++虚函数表

2010-02-01 11:22:09

C++虚函数

2022-07-18 15:32:37

C++虚函数表

2009-12-29 13:40:24

使用ADO.NET

2009-12-25 15:47:20

ADO存储过程

2011-05-24 16:20:27

虚函数

2010-02-04 11:23:14

Android操作系统

2024-04-22 13:22:00

虚函数象编程C++

2024-01-23 10:13:57

C++虚函数

2010-01-20 18:06:06

C++虚基类

2010-01-25 18:12:28

C++

2010-01-14 18:19:40

C++语言

2010-01-13 10:37:55

C++开发

2009-12-18 13:46:16

Visual Web
点赞
收藏

51CTO技术栈公众号