返回首页
0
0

C++ 中虚函数的一些笔记

xiaoxin 发表于 2012年03月03日 01:40 | Hits: 1568
Tag: Note

首先推荐一本书《C++高级编程》,花了一个下午的时间在看这本书,感觉这本书翻译的相当不错,讲的也通俗易懂。

说来惭愧,虚函数是一个我一直很迷惑的东西,但后来发现这个确实是C++中非常强大的一个特性。书上建议把所有的成员函数都声明成虚函数,至少析构函数必须是虚函数。先运行两段试验的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
using namespace std;
 
class Super{
	public:
		void foo(){
			cout<<"Super Foo"<<endl;
		}
		void bar(){
			cout<<"Super Bar"<<endl;
		}
};
 
class Sub:public Super{
	public:
		void foo(){
			cout<<"Sub Foo"<<endl;
		}
};
 
int main()
{
	Sub sub;
	sub.foo();
	Super& xx = sub;
	xx.foo();
	return 0;
}

输出的结果:

[xiaoxin@Archlinux test]$ ./test
Sub Foo
Super Foo

上面,子类重载了父类的foo方法,但当它转换成超类时,确输出了超类的方法,超类的foo方法还在
另一段代码,将函数都声明成虚函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
using namespace std;
 
class Super{
	public:
		virtual void foo(){
			cout<<"Super Foo"<<endl;
		}
		virtual void bar(){
			cout<<"Super Bar"<<endl;
		}
};
 
class Sub:public Super{
	public:
		virtual void foo(){
			cout<<"Sub Foo"<<endl;
		}
};
 
int main()
{
	Sub sub;
	sub.foo();
	Super& xx = sub;
	xx.foo();
	return 0;
}

代码的输出为

[xiaoxin@Archlinux test]$ ./test
Sub Foo
Sub Foo

这里尽管子类被转换成超类,但并没有实现超类的foo方法,也就是说,超类的foo被子类所覆盖
做个类比,子类中有堆中的数据,这些数据在子类的虚构函数中销毁,如果析构函数没声明成虚函数,而且子类指针又恰好不小心被转换成了超类的指针,然后delete it,那么它将不会调用子类的虚构函数,然后将内存泄漏事故
为何如此还得看虚函数在c++中的实现:

其实很像unix文件系统中硬连接的实现方法。在包含有虚函数的类中都会另外开辟一片内存区域一存放虚函数表,虚函数表存放的是相应函数的指针,若子类没重载超类的虚函数,则直接继承超类的指针,否则,将子类的指针指向重载的实现。当子类被强制转换成了超类时,其重载的指针指向的是同一个内存区,也就相当与真正实现了覆盖(其实java中就是这么干的)。如果没声明成虚函数,那么子类仅仅是隐藏了超类的实现,当它又“变回超类”时就原形毕露了。
正是由于这个特性,虚函数才是实现多态的基础。因为子类指针向上转换成超类指针时,相应的方法并没改变,也就实现了安全的转换。

原文链接: http://xiaoxins.com/archives/426

0     0

评价列表(0)

返回首页