虚函数

    C++对C的贡献之一是函数调用的动态绑定,C++把类型解析惹火我转交给编译器实现,从而减轻了程序员的负担,这是它的优点,但是另外一个方面,它带来负面作用,即开销过大。

3.1 虚函数的构造

 C++ Code 
1
2
3
4
5
6
7
void drawAllAnimals(ZooAnimal *pz)  //指向列表中第一个动物的指针。
{
     for(ZooAnimal *p = pz; p; p = p->next)
    {
        p->draw(); //由于draw是虚函数,是实现动态绑定。
    }
}
   为了识别动物属性,我们采用后期绑定。但是这是一种运行时绑定,会造成开销。在以下方面,虚函数可能会造成性能损失。

1、构造函数必须初始化vptr。

2、虚函数是通过指针间接调用的,所以必须先得到指向虚函数表的指针,然后再获得正确的函数偏移量。

3、内联是在编译时决定的。编译器不可能把运行时才解析的虚函数设置为内联。


为了消除虚函数调用带来的问题,我们可以通过硬编码或者将它作为模板参数来传递,可以避免使用动态绑定。


3.2 模板和继承

    我们想要开发一个线程安全的string类。

    Locker抽象基类将声明公共接口:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Locker
{
public:
    Locker() {}
     virtual ~Locker() {}
     virtual  void lock() =  0;
     virtual  void unlock() =  0;
};
//CriticalSectionLock和MutexLock将从基类Locker派生出来
class CriticalSectionLock:  public Locker
{
    ...
};
class MutexLock:  public Locker
{
    ...
};
   因为我们不想重新设计,所以选择从现有标准的string类派生出线程安全的string类。余下的设计选项是:

1、硬编程  

     可以从string类中派生出三个独立类:CriticalSectionString、MutexString和SemaporeString 。每个类实现各自名字所代表的同步机制。


2、继承

    可以派生出一个单独的ThreadSafeString 类,它包含执行Locker对象的指针。在运行期间通过多态机制选择特定的同步机制。


3、模板

    基于模板的string类,该类由Locker类型参数化后得到。


首先是硬编码的版本:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class CriticalSectionString:  public string
{
public:
    ...
     int length();
private:
    CriticalSectionLock cs;
}
int CriticalSectionString::length()
{
    cs.lock();
     int len = string::length();
    cs.unlock();
     return len;
}
    类似的,MutexString和SemaphoreString各自通过互斥和信号机制来实现。

    尽管lock()和unlock()是虚函数,不过可以通过编译器进行静态的解析。

再然后是继承的版本:不能实现内联,所以带来性能损失。

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class ThreadSafeString:  public string
{
public:
    ThreadSafeString( const  char *s, Locker *lockPtr)
        : string(s), pLock(lockPtr) {}
    ...
     int length();
private:
    Locker *pLock;
}
int ThreadSafeString::length()
{
    pLock->lock();
     int len = string::length();
    pLock->unlock();
     return len;
}
//使用方法如下
{
    CriticalSectionLock cs;
    ThreadSafeString csString( "hello", cs);  //可以静态绑定
}


最后看模板的实现:

基于模板的设计结合了两个方面的优点:重用和效率。ThreadSafeString是作为模板实现的,它的参数由Locker模板参数决定。实现如下:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
template< class LOCKER>
class ThreadSafeString:  public string
{
public:
    ThreadSafeString( const  char *s): string(S) {}
    ...
     int length();
private:
    LOCKER lock;
};
template < class LOCKER>
inline
int ThreadSafeString<LOCKER>::length()
{
    lock.lock();
     int len = string::length();
    lock.unlock();
     return len;
}
//我们可以实现静态绑定。
{
    ThreadSafeString <CriticalSectionLock> csString =  "hello";
    ...
}
    模板把计算从执行期间提前到编译期间来做,并且在编译时使用内联,因此提高了性能。

   

3.3 要点


1、虚函数的代价在于无法内联函数调用,因为这些调用是在运行时动态绑定的。

2、模板比继承提供更好的性能,它把对类型的解析提前到编译期间,我们认为这是没有成本的。














评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值