C++关键字之virtual

from://http://blog.csdn.net/xuyuanfan/article/details/9935533

在C++中是没有接口的,要真正实现java中的interface功能,需要使用virtual函数的多态继承机制。这里就细讲一下C++中的virtual关键字的用法。

首先设计3个类,包括book、good_book和bad_book。book为基类,而good_book和bad_book继承于book类。

1、book类:包括一个成员变量name和一个虚成员函数getName

2、good_book类:只有一个成员函数getName

3、bad_book类:只有一个成员函数getName

其中book、good_book和bad_book这3个类的getName是同名同参数列表同返回值的成员函数。

三个类的UML图如下:

三个类的源代码如下:

book类的头文件:book.h

  1. #ifndef _BOOK_H_  
  2. #define _BOOK_H_  
  3.   
  4. #include <string>  
  5.   
  6. using namespace std;  
  7.   
  8. class  book{  
  9. protected:  
  10.        string name;  
  11. public:  
  12.        book();  
  13.        virtual string getName();  
  14. };  
  15.   
  16. #endif  

book类的源文件:book.cpp

  1. #include "book.h"  
  2.   
  3. book::book()  
  4. {  
  5. name = "book";  
  6. }  
  7.   
  8. string book::getName(){  
  9. return name;  
  10. }  

good_book类的头文件:good_book.h

  1. #ifndef _GOOD_BOOK_H_  
  2. #define _GOOD_BOOK_H_  
  3.   
  4. #include "book.h"  
  5.   
  6. using namespace std;  
  7.   
  8. class good_book : public book{  
  9. public:  
  10.       string getName();   
  11. };  
  12. #endif  

good_book类的源文件:good_book.cpp

  1. #include "good_book.h"  
  2.   
  3. string good_book::getName(){  
  4. return "good "+name;  
  5. }  

bad_book类的头文件:bad_book.h

  1. #ifndef _BAD_BOOK_H_  
  2. #define _BAD_BOOK_H_  
  3.   
  4. #include "book.h"  
  5.   
  6. using namespace std;  
  7.   
  8. class bad_book : public book{  
  9. public:  
  10.       string getName();   
  11. };  
  12. #endif  

bad_book类的源文件:bad_book.cpp

  1. #include "bad_book.h"  
  2.   
  3. string bad_book::getName(){  
  4. return "bad "+name;  
  5. }  

三个类都设计好了,那现在设计场景(main函数)来运用这三个类,源代码如下:

场景文件:main.cpp

  1. #include <iostream>  
  2. #include <string>  
  3. #include "book.h"  
  4. #include "good_book.h"  
  5. #include "bad_book.h"  
  6.   
  7. using namespace std;  
  8.   
  9. int main()  
  10. {  
  11.     int pause;  
  12.     cout<<"=================================================================="<<endl;  
  13.     cout<<"使用指向基类的指针bk(指向基类对象book)"<<endl;  
  14.     book *bk;  
  15.     bk = new book();  
  16.     cout<<bk->getName()<<endl;  
  17.     delete(bk);  
  18.       
  19.     cout<<"使用指向基类的指针bk(指向派生类对象good_book)"<<endl;  
  20.     bk = new good_book();  
  21.     cout<<bk->getName()<<endl;  
  22.     delete(bk);  
  23.       
  24.     cout<<"使用指向基类的指针bk(指向派生类对象bad_book)"<<endl;  
  25.     bk = new bad_book();  
  26.     cout<<bk->getName()<<endl;  
  27.     delete(bk);  
  28.     cout<<"=================================================================="<<endl;  
  29.     cout<<"使用指向派生类的指针bks(指向基类对象book)"<<endl;  
  30.     cout<<"不可以"<<endl;    
  31.     //    good_book *bks;  
  32.     //    bks = new book();  
  33.     //    cout<<bk->getName()<<endl;  
  34.     //    delete(bk);  
  35.       
  36.     cout<<"使用指向派生类的指针bks(指向派生类对象good_book)"<<endl;  
  37.     good_book *bks;  
  38.     bks = new good_book();  
  39.     cout<<bk->getName()<<endl;  
  40.     delete(bk);  
  41.   
  42.     cout<<"使用指向派生类的指针bks(指向基类的其他派生类对象bad_book)"<<endl;  
  43.     cout<<"不可以"<<endl;   
  44.     //    good_book *bks;      
  45.     //    bks = new bad_book();  
  46.     //    cout<<bk->getName()<<endl;  
  47.     //    delete(bk);  
  48.     cout<<"=================================================================="<<endl;  
  49.     cout<<"使用基类实例对象Obk"<<endl;   
  50.     book Obk;  
  51.     cout<<Obk.getName()<<endl;  
  52.       
  53.     cout<<"使用派生类实例对象Ogood_book"<<endl;   
  54.     good_book Ogood_book;  
  55.     cout<<Ogood_book.getName()<<endl;  
  56.       
  57.     cout<<"使用派生类实例对象Obad_book"<<endl;   
  58.     bad_book Obad_book;  
  59.     cout<<Obad_book.getName()<<endl;  
  60.       
  61.     cin>>pause;  
  62.     return 0;  
  63. }  


编译运行程序,得出结果:

由输出结果可以知道,在两个派生类继承并覆写了基类的虚函数的情况下:

1、使用基类类型指针,那它指向哪个对象实例就会调用哪个对象的函数;

2、使用派生类类型指针,它不能指向基类和该基类的其他派生类,只能指向该派生类对象并调用该派生类对象的函数;

3、使用对象实例,那使用的是哪个对象实例就会调用哪个对象的函数。

在这里,再把该虚函数改为普通函数,即把book.h 文件的getName函数前面的virtual关键字给去掉,源代码如下:

book类的头文件:book.h

  1. #ifndef _BOOK_H_  
  2. #define _BOOK_H_  
  3.   
  4. #include <string>  
  5.   
  6. using namespace std;  
  7.   
  8. class  book{  
  9. protected:  
  10.        string name;  
  11. public:  
  12.        book();  
  13.        string getName();  
  14. };  
  15.   
  16. #endif  


再次编译运行程序,得出结果:

对照没去掉virtual关键字运行的结果可知道,唯一的区别就是——若使用基类类型指针,那不管它指向哪个对象实例都会调用基类对象的函数;

原文地址:https://www.cnblogs.com/wanqieddy/p/3313989.html