C++是如何利用虚函数实现多态性的?

转载 2012年03月28日 23:04:54

前一篇:http://patmusing.blog.163.com/blog/static/1358349602010419111919799/

还是先看示例程序,用代码说话:

#include <iostream>

using namespace std;

 

class A

{

public:

         inline virtual void vfun()

         {

                   cout << "this is vfun in class A" << endl;

         }

};

 

class B : public A

{

public:

         inline void vfun()

         {

                   cout << "this is vfun in class B" << endl;

         }

};

 

int main(void)

{

         A* p;

         A P;

         // 由于A中声明了虚函数,那么在定义对象P时,P中将包含A类的vfptr

         // vfptr指向A类的虚函数表,

         p = &P;

         // 因此下面的语句向显示”this is vfun in class A

         p->vfun();

 

         B* q;

         // 由于A中声明了虚函数,类B继承了A,那么在定义对象Q时,Q中将包含B

         // 类的vfptr,该vfptr指向B类的虚函数表

         B Q;

         q = &Q;

         p = q;

         // p 现在是类B对象的一个指针,即Q的地址,而Q中包含了指向B类虚函数

         // 表的vfptr指针。因此下面的语句将显示

         // “this is vfun in class B”

         p->vfun();

 

         return 0;

}

当然在实际编程中,没有人会象上面那样写程序的。运行结果:

C++是如何利用虚函数实现多态性的? - 玄机逸士 - 玄机逸士博客


再来一个虚函数和多态性例子:

#include <iostream>

using namespace std;

 

class Parent

{

public:

         int parent;

 

public:

         inline Parent()

         {

         }

 

         inline Parent(int parent)

         {

                   this->parent = parent;

         }

 

         inline virtual void haveFun()

         {

                   cout << "haveFun in Parent" << endl;

                   cout << "parent = " << parent << endl;

         }

};

 

class Child : public Parent

{

public:

         int child;

 

public:

         inline Child()

         {

         }

 

         inline Child(int child) : Parent(child + 1)

         {

                   this->child = child;

         }

 

         inline void haveFun()

         {

                   cout << "haveFun in Child" << endl;

                   cout << "parent = " << parent << endl;

                   cout << "child = " << child << endl;

         }

};

 

int main(void)

{

         Parent* p = new Child(2);

         p->haveFun();

 

         return 0;

}

输出结果:

C++是如何利用虚函数实现多态性的? - 玄机逸士 - 玄机逸士博客
 

这正是我们希望看到的现象。但是如果我们把Parent类中haveFun函数前面的virtual去掉,结果会是什么样子呢?

C++是如何利用虚函数实现多态性的? - 玄机逸士 - 玄机逸士博客
 

多态性不见了,因此可以推论,没有虚函数就没有多态性。究竟背后是什么原因造成的呢?

 

我们知道如果一个类声明了虚函数,那么编译器就会在其声明的对象中的开始部分(至少对于VC而言是这样的)增加一个vfptrvfptr指向虚函数表。如果没有声明虚函数,那么这vfptr就不存在。Parent* p是声明了一个指向Parent对象的指针,Parent没有声明虚函数的情况下,p所指向的内容并不包括vfptr,当用new Child(2)给它赋值时,除了将Child中的Parent subojectmemberwise的方式拷贝给p所指向的Parent对象外,什么也没有做。因此p->haveFun()调用的是 Parent中的haveFun函数;

 

如果在ParenthaveFun是虚函数,那么当Parent* p = new Child(2);执行时,就会把Child对象的vfptrChild对象中包含的Parent subobject一同以memberwise的方式拷贝给p所指向的对象。此后,p所指向vfptrChild对象的vfptr,因此再调用 p->havefun()时,就会调用Child类中的haveFun函数。另外值得一提的是,如果不进行explicit形式的类型转换p所指的对象只有vfptr(vfptr得到虚函数haveFun)Parent::parent,在VC中的表现如下:

C++是如何利用虚函数实现多态性的? - 玄机逸士 - 玄机逸士博客

既然我们对p的初始化是Parent* p = new Child(2),即是通过一个Child对象的指针来初始化的,为什么p中看不到Child中的child成员变量呢?原因是Parent* p所隐含的意思是,p指向一个Parent对象,包括vfptr在内共8 bytesChild*所隐含的意思是,它所指向的是一个Child对象,包括vfptr在内共12 bytes,如下图:

C++是如何利用虚函数实现多态性的? - 玄机逸士 - 玄机逸士博客
 

Parent* p = new Child(2)执行时,会发生如下图所示的过程:

C++是如何利用虚函数实现多态性的? - 玄机逸士 - 玄机逸士博客
 

也就是说,p所指向的内存块有vfptrparent以及child,只是由于 Parent的大小为8 bytes,因此限制了p缺省地只能看到8 bytes,如果用Child*p进行指针类型的转换,就可以看到12 bytes,也就是说可以看到Child的成员变量child了,如下:

C++是如何利用虚函数实现多态性的? - 玄机逸士 - 玄机逸士博客

利用C++模板,代替虚函数实现类的静态多态性及动态继承

转自:http://blog.csdn.net/nancy_m/article/details/8691681 熟悉模板编程的朋友或许听到过这个技巧或者模式:Barton-Nackm...

利用C++模板,代替虚函数实现类的静态多态性及动态继承

熟悉模板编程的朋友或许听到过这个技巧或者模式:Barton-Nackmann 技巧或者称 奇异循环模板模式(Curiously Recurring Template Prattern)。      ...
  • Nancy_m
  • Nancy_m
  • 2013年03月19日 14:45
  • 3322

利用C++模板,代替虚函数实现类的静态多态性及动态继承

利用C++模板,代替虚函数实现类的静态多态性及动态继承 分类: C++基础知识 C++编程思想2013-03-19 14:45 456人阅读 评论(0) 收藏 举报 熟悉模板编...

C++是如何利用虚函数实现多态性的?

#include using namespace std; class A { public:          inline virtual vfun()          { ...
  • Joogle
  • Joogle
  • 2012年08月29日 17:21
  • 175

利用C++模板,代替虚函数实现类的静态多态性

熟悉模板编程的朋友或许听到过这个技巧或者模式:Barton-Nackmann 技巧或者称 奇异循环模板模式(Curiously Recurring Template Prattern)。     其...

C++是如何利用虚函数实现多态性的?

还是先看示例程序,用代码说话:#include iostream>using namespace std; class A{public:inline virtual void vfun(){cout...

利用C++模板,代替虚函数,实现类的静态多态性(加入性能测试部分)

http://www.cppblog.com/woaidongmao/archive/2008/05/22/50805.html 利用C++模板,代替虚函数,实现类的静态多态性(加入性能测试部分) ...

C++是如何利用虚函数实现多态性的?

还是先看示例程序,用代码说话: #include using namespace std;   class A { public:          inline virtual vf...

C++继承,虚函数与多态性专题.

  • 2012年05月05日 19:35
  • 333KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++是如何利用虚函数实现多态性的?
举报原因:
原因补充:

(最多只允许输入30个字)