源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

深入理解c++中virtual关键字

  • 时间:2020-04-04 14:03 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:深入理解c++中virtual关键字
[b]1.virtual关键字主要是什么作用? [/b]c++中的函数调用默认不适用动态绑定。要触发动态绑定,必须满足两个条件:第一,指定为虚函数;第二,通过基类类型的引用或指针调用。 由此可见,virtual主要主要是实现动态绑定。 [b]2.那些情况下可以使用virtual关键字? [/b]virtual可用来定义类函数和应用到虚继承。 友元函数 构造函数 static静态函数 不能用virtual关键字修饰; 普通成员函数 和析构函数 可以用virtual关键字修饰; [b]3.virtual函数的效果 [/b]
[u]复制代码[/u] 代码如下:
class GrandFather { public:  GrandFather() {}  virtual void fun()  {   cout << "GrandFather call function!" << endl;  } }; class Father : public GrandFather { public:   Father() {}   void fun()   {    cout << "Father call function!" << endl;   } }; class Son : public Father { public:  Son() {}  void fun()  {   cout << "Son call function!" << endl;  } }; void print(GrandFather* father) {  father->fun(); } int _tmain(int argc, _TCHAR* argv[]) {  Father * pfather = new Son;         pfather->fun();         GrandFather * pgfather = new Father;         print(pgfather);  return 0; }
输出为 Son call function        Father call function [b]4.virtual的继承性 [/b]只要基函数定义了virtual,继承类的该函数也就具有virtual属性 即 GrandFather Father Son同时定义virtual void fun()与GrandFather一个定义virtual void fun效果是一样的 [b]5.虚析构函数 [/b]
[u]复制代码[/u] 代码如下:
class GrandFather { public:  GrandFather() {}  virtual void fun()  {   cout << "GrandFather call function!" << endl;  }  ~GrandFather()  {   cout << "GrandFather destruction!" << endl;  } }; class Father : public GrandFather { public:  Father() {}  void fun()  {   cout << "Father call function!" << endl;  }  ~Father()  {   cout << "Father destruction!" << endl;  } }; class Son : public Father { public:  Son() {}  void fun()  {   cout << "Son call function!" << endl;  }   ~Son()  {   cout << "Son destruction!" << endl;  } }; void print(GrandFather* p) {  p->fun(); } int _tmain(int argc, _TCHAR* argv[]) {  Father * pfather = new Son;  delete pfather;  return 0; }
以上代码输出:Father destruction!                              GrandFather destruction! 执行了Son的构造函数,没执行Son的析构函数,故把GrandFather的析构函数设置为virtual 则输出: Son destruction!         Father Destruction!         GrandFather destruction! [b]6. 纯虚函数 [/b]纯虚函数定义如下:
[u]复制代码[/u] 代码如下:
class GrandFather { public:  GrandFather() {}  virtual void fun() = 0  {   cout << "GrandFather call function!" << endl;  }  virtual ~GrandFather()  {   cout << "GrandFather destruction!" << endl;  } };
纯虚函数为后代类提供可覆盖的接口,但这个类中的版本决不会调用。 含有(或继续)一个或多个纯虚函数的类是抽象基类,抽象基类不能实例化! 继承类只有重写这个接口才能被实例化 [b]7.虚继承 [/b]虚继承主要解决交叉继承带来的问题。这里给出一片参考文章c++虚继承。 给一个例子如下
[u]复制代码[/u] 代码如下:
class GrandFather { public:  GrandFather() {}  void fun()  {   cout << "GrandFather call function!" << endl;  }  virtual ~GrandFather()  {   cout << "GrandFather destruction!" << endl;  } }; class Father1 : public GrandFather { public:  Father1() {}  void fun()  {   cout << "Father call function!" << endl;  } }; class Father2 : public GrandFather { public:  Father2() {}  void fun()  {   cout << "Father call function!" << endl;  } }; class Son : public Father1, public Father2 { public:  Son() {}  //void fun()  //{  // cout << "Son call function!" << endl;  //} }; void print(GrandFather* p) {  p->fun(); } int _tmain(int argc, _TCHAR* argv[]) {  Son* son = new Son;  son->fun();  return 0; }
编译时会提示报错对fun的访问不明确 如果Father1和Father2都用虚继承继承GrandFather类则可以解决这个问题 [b]8. 构造函数和析构函数中的虚函数 [/b]如果在构造函数或析构函数中调用虚函数,则运行的是为构造函数或析构函数自身类型定义的版本 [b]9.虚函数的实现机制 [/b]关于虚函数的实现机制,我们以后在介绍。 [b]10.小结 [/b]关于virtual关键字的用法总结如上,有错误或者总结不到位的情况请能帮本人指出! [b]11.例子 [/b]
[u]复制代码[/u] 代码如下:
class classA {  public:  classA()  {   clear();  }  virtual ~classA()  {  }  void clear()  {   memset(this , 0 , sizeof(*this));  }  virtual void func()  {   printf("func\n");  } }; class classB : public classA { }; int main(void) {  classA oa;  classB ob;  classA * pa0 = &oa;  classA * pa1 = &ob;  classB * pb = &ob;  oa.func(); // 1  ob.func(); // 2  pa0->func(); // 3  pa1->func(); // 4  pb->func(); // 5  return 0; }
补充一个例子,这个程序输出依次是 func func 出错 func func 谈谈我的理解,当 classA oa; oa.func(); 不存在动态调用的过程,所以func虽然是虚函数,但是函数调用不通过虚表访问,所以即使
[u]复制代码[/u] 代码如下:
memset(this , 0 , sizeof(*this));
找不到虚表地址也没有关系 在执行classB ob;的时候,注意memset的是classA的地址,所有ob的虚表是存在的 即是如下,通过指针或引用(动态绑定)访问oa的func函数(需要从虚表访问),会出错 访问ob的func和函数,无论静态访问还是动态访问,都不会出错 当把classB的代码改成如下时
[u]复制代码[/u] 代码如下:
class classB : public classA <PRE style="FONT-WEIGHT: bold" class=cpp name="code">{</PRE><PRE style="FONT-WEIGHT: bold" class=cpp name="code">        classB()  {   clear();  }  virtual ~classB()  {  }  void clear()  {      memset(this , 0 , sizeof(*this));  }</PRE><BR> <PRE></PRE> <PRE style="FONT-WEIGHT: bold" class=cpp name="code">};</PRE>输出为
func func 出错 出错 出错
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部