读书笔记:11章什么时间不适合使用虚函数1

C++沉思录第十一章读书笔记1[@more@]

第十一章:什么时间不适宜使用虚函数?

第九章没有用虚函数解决了一个相当困难的问题,第十章解决了同样的问题,但是必须采用虚函数。

11-1 使用的情况

如果只关注程序的行为,同时没有继承关系,那么函数是否为虚函数无关紧要。

一个例子:一个整数数组的IntArray类:

class IntArray {

public:

//....

unsigned size() const;

int& operator[] {unsigned n};

};

我们可以写一个函数来将数组的所有元素设置为零。

void zero{IntArray &x)

{

for(int i = 0; i < x.size(); i++)

x[n] = 0;

}

类似这样的情况,应该设置为虚函数。如果有人希望从IntArray派生出一个类IntFileArray,该类的文件中而不是直接在内存中保存这些整数。如果IntArray::operator[]IntrArray::size()是虚函数,那么zero函数在IntFileArray对象中也能正常运行。

11-2 不适用的情况

虚函数的代价并不是很高昂,但也不是免费的午餐。

有些情况下非虚函数能够正确运行,而虚函数却不行。

不是所有的类都是为了继承而设计的

11-2-1 效率

想要知道某个程序在这方面的实际开销,必须在不同的机器上测量开销,通过对内存引用进行计数来获得一个大概值是可能的。

int& IntArray::operator[] (unsigned n)

{

if (n>= arraysize)

throw "subsctipt out of range");

return data[n];

}

除了调用函数的开销外,还需要3个内存引用,以便分别获得n, arraysize, data的值。怎样将这样开销和调用虚函数的开销进行比较?此外怎样将这个开销与调用非虚成员函数的开销进行比较?

因为假设开销足够大,所以把这个函数内联。因此,一个好的实现通过对象使用operator[]时根本不会因入新得开销。通过指针或者引用operator[]的开销可能与3个内存引用有关:一个是对指针本身的;成员函数初始化this指针的;调用返回序列的。因此通过指针或者引用来调用这个函数所花的时间是两倍。调用一个虚函数通常有三个内存引用取出:描述对象类型的表的地址值;虚函数的地址;本对象的偏移量。所以三倍于执行时间。

class InputBuffer {

public:

//...

virtual int get();

//...

};

计算缓冲区的行数。

int countlines(InputBuffer& b)

{

int n = 0;

int c;

while((c= b.ger()) != EOF) {

if (c == '')

n++;

}

return n;

}

这个函数对于所有InpubBuffer 的派生类都有效这一点来说,他是很灵活的,每个对get的调用都是虚函数调用,所以要消耗掉6个内存引用。3个函数固有,3个虚函数开销。

如果认识到,使用缓冲区的应用程序很可能是要一次性的访问多个字符,那么应InputBuffer 类的设计做的好的多。

class InputBuffer {

public:

//.....

int get() {

if(next >= limit)

return refill();

return *next++;

}

protected:

virtual int refill();

private:

char * nect;

char * limit;

};

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/409557/viewspace-892342/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/409557/viewspace-892342/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值