虚函数、虚析构函数的缺点

来源:计算机等级考试    发布时间:2012-08-29    计算机等级考试视频    评论

  然而,仅仅是了解到这一点还不够,面试中面试官往往会进一步问你,虚函数有什么缺点(有的会问,析构函数声明为虚函数有什么缺点)?
  大体原因如下:如果某个类不包含虚函数,那一般是表示它将不作为一个基类来使用。当一个类不准备作为基类使用时,使析构函数为虚一般是个坏主意。因为它会为类增加一个虚指针、一个虚函数表,使得对象的体积翻倍,并会降低其可移植性。
  所以基本的一条是:无故的声明虚析构函数和永远不去声明一样是错误的。实际上,很多人这样总结:当且仅当类里包含至少一个虚函数的时候才去声明虚析构函数。
  也许有的地方会提到另一个可能,在析构到基类的时候,派生类的书数据已经destruct掉了,所以可能会引用了corrupted数据。这个分析得是对的,但是结论错了,因为C++规范保证了,在析构掉派生类部分之 后,再调虚函数的时候会调基类的虚函数。
  这里我们用具体代码来详细解释,为什么不把所有的析构函数都声明为虚函数?
  如果一个类不包含虚函数,这经常预示不打算将它作为基类使用。当一个类不打算作为基类时,将析构函数声明为虚拟通常是个坏主意。考虑一个表现二维空间中的点的类:
  class Point { // a 2D point
  public:
  Point(int xCoord, int yCoord);
  ~Point();
  private:
  int x, y;
  };
  如果一个 int 占 32 位,一个 Point 对象正好适用于 64 位的寄存器。而且,这样一个 Point 对象可以被作为一个 64 位的量传递给其它语言写的函数,比如 C 或者 FORTRAN。如果 Point 的析构函数是虚拟的,情况就完全不一样了。
  虚函数的实现要求对象携带额外的信息,这些信息用于在运行时确定该对象应该调用哪一个虚函数。典型情况下,这一信息具有一种被称为 vptr(virtual table pointer,虚函数表指针)的指针的形式。vptr 指向一个被称为 vtbl(virtual table,虚函数表)的函数指针数组,每一个包含虚函数的类都关联到 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 做出明确的对应,而这是它自己的实现细节并因此失去可移植性。
  STL里的容器都没有虚析构函数!
  全部的 STL 容器类型(例如,vector,list,set,tr1::unordered_map。如果你受到从标准容器类或任何其他带有非虚析构函数的类派生的诱惑,一定要挺住!
  纯虚析构函数
  有时候,你有一个类,你希望它是抽象的,但没有任何纯虚函数。怎么办呢?因为一个抽象类注定要被用作基类,又因为一个基类应该有一个虚析构函数,又因为一个纯虚函数产生一个抽象类,好了,解决方案很简单:在你希望成为抽象类的类中声明一个纯虚析构函数。这是一个例子:
  class AWOV { // AWOV = "Abstract w/o Virtuals"
  public:
  virtual ~AWOV() = 0; // declare pure virtual destructor
  };
  这个类有一个纯虚函数,所以它是抽象的,而且它有一个虚析构函数,所以不会产生析构函数问题。但这里还有一件事:必须为纯虚析构函数提供一个定义:
  AWOV::~AWOV() {} // definition of pure virtual dtor
  析构函数的工作方式是:最底层的派生类(most derived class)的析构函数最先被调用,然后调用每一个基类的析构函数。编译器会产生一个从派生类的析构函数对 ~AWOV 的调用,所以你不得不确实为函数提供一个函数体。如果不这样做,链接器就会检测出来,最后还是得回去把它添上。

  编辑特别推荐:

  c++对插入排序的改进

视频学习

我考网版权与免责声明

① 凡本网注明稿件来源为"原创"的所有文字、图片和音视频稿件,版权均属本网所有。任何媒体、网站或个人转载、链接转贴或以其他方式复制发表时必须注明"稿件来源:我考网",违者本网将依法追究责任;

② 本网部分稿件来源于网络,任何单位或个人认为我考网发布的内容可能涉嫌侵犯其合法权益,应该及时向我考网书面反馈,并提供身份证明、权属证明及详细侵权情况证明,我考网在收到上述法律文件后,将会尽快移除被控侵权内容。

最近更新

社区交流

考试问答