ITPub博客

首页 > 应用开发 > IT综合 > 读书笔记:11章什么时间不适合使用虚函数1

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

原创 IT综合 作者:karlyang88 时间:2007-01-22 14:23:16 0 删除 编辑
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/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
  • 博文量
    35
  • 访问量
    331868