设为首页 加入收藏

TOP

4.4.2 虚函数
2013-10-07 15:03:57 来源: 作者: 【 】 浏览:62
Tags:4.4.2 函数

4.4.2  虚函数

虚函数有两部分的开销:首先,与调用一个外联的非虚函数相比,调用一个外联的虚函数需要增加一些额外的机器指令。除非这个函数调用的频率非常高,否则这个效率的影响并不大。其次,也是更重要的影响因素,在大多数调用上下文中,现今的编译器并不能内联虚函数。为了说明这个问题,考虑4.4.2节开头给出的BSTree::size函数,我们现在把这个函数如下声明为虚函数:

  1. template<class T> 
  2.     class BSTree {  
  3.          virtual inline int size() const {  
  4.               return  _size;  
  5.          }  
  6.          //...  
  7.     };  

如果上下文可以很容易地静态确定是在BSTree对象调用这个函数BSTree::Size(而不是在其派生类的某个对象上调用),那么大多数编译器就可以内联BSTree::size函数:
  1. BSTree<int> b;  
  2.    //...  
  3.    int sz = b.size();    //这里大多数编译器都可以内联。  

另一方面,如果不能(或者很困难)决定BSTree::size是否在BSTree对象本身上调用,那么现有的大多数编译器就不能内联BSTree::size:
  1. void f(  const BSTree<int>& b) {  
  2.        int sz=b.size();  //大多数编译器都不能内联;这里的b是一个引用类型,b面的不是  
  3.        //...  
  4.    }  

因此,基于现在的编译器技术,当我们需要把一个函数声明为虚函数时,我们就放弃了在大多数上下文内联这个函数的能力。关于是否内联一个函数或者把这个函数声明为虚函数问题,我们在表4.2给出了总结。

如果内联成员函数f是至关重要的,而用户又需要改写f,那就需要寻找某种重新设计并可以解决这个冲突的办法。幸运的是,在实际中这种冲突出现的几率很小。

如果内联成员函数f是至关重要的,并且用户不需要改写f,那么就应该把f声明为非虚内联函数。

如果内联不太重要,并且用户需要改写这个函数,那么就应该把f声明为非内联的虚函数。

最后,如果内联和改写都不是很重要,那么f就应该被声明为非虚函数,才能避免调用虚函数所花费的开销。

表4.2 成员函数是否应该声明为内联函数或者函数

用户是否需要改写< xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

内联是否至关重要

重新设计程序库

非内联的虚函数

非虚内联函数

非虚函数,见表4.1

当然,要想知道哪些函数是用户需要改写的函数是非常困难的(见3.4.1节)。当有这方面疑问(即是否需要改写)的时候,我们就应该把函数声明为非虚函数;否则当真正需要改写函数时,用户肯定会不知所措(除非函数的源代码已经分发,用户可以得到源代码,见3.6节)。

几乎没有函数可以既声明为虚函数,又声明为内联函数。因为当这类函数的调用不能被内联的时候,将有可能在每个翻译单元中都生成一份这类函数的外联拷贝(见4.3.2节和4.4.2节)。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇4.4.3 返回引用 下一篇4.6.2 使用更加困难

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: