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
- #ifndef _BOOK_H_
- #define _BOOK_H_
- #include <string>
- using namespace std;
- class book{
- protected:
- string name;
- public:
- book();
- virtual string getName();
- };
- #endif
book类的源文件:book.cpp
- #include "book.h"
- book::book()
- {
- name = "book";
- }
- string book::getName(){
- return name;
- }
good_book类的头文件:good_book.h
- #ifndef _GOOD_BOOK_H_
- #define _GOOD_BOOK_H_
- #include "book.h"
- using namespace std;
- class good_book : public book{
- public:
- string getName();
- };
- #endif
good_book类的源文件:good_book.cpp
- #include "good_book.h"
- string good_book::getName(){
- return "good "+name;
- }
bad_book类的头文件:bad_book.h
- #ifndef _BAD_BOOK_H_
- #define _BAD_BOOK_H_
- #include "book.h"
- using namespace std;
- class bad_book : public book{
- public:
- string getName();
- };
- #endif
bad_book类的源文件:bad_book.cpp
- #include "bad_book.h"
- string bad_book::getName(){
- return "bad "+name;
- }
三个类都设计好了,那现在设计场景(main函数)来运用这三个类,源代码如下:
场景文件:main.cpp
- #include <iostream>
- #include <string>
- #include "book.h"
- #include "good_book.h"
- #include "bad_book.h"
- using namespace std;
- int main()
- {
- int pause;
- cout<<"=================================================================="<<endl;
- cout<<"使用指向基类的指针bk(指向基类对象book)"<<endl;
- book *bk;
- bk = new book();
- cout<<bk->getName()<<endl;
- delete(bk);
- cout<<"使用指向基类的指针bk(指向派生类对象good_book)"<<endl;
- bk = new good_book();
- cout<<bk->getName()<<endl;
- delete(bk);
- cout<<"使用指向基类的指针bk(指向派生类对象bad_book)"<<endl;
- bk = new bad_book();
- cout<<bk->getName()<<endl;
- delete(bk);
- cout<<"=================================================================="<<endl;
- cout<<"使用指向派生类的指针bks(指向基类对象book)"<<endl;
- cout<<"不可以"<<endl;
- // good_book *bks;
- // bks = new book();
- // cout<<bk->getName()<<endl;
- // delete(bk);
- cout<<"使用指向派生类的指针bks(指向派生类对象good_book)"<<endl;
- good_book *bks;
- bks = new good_book();
- cout<<bk->getName()<<endl;
- delete(bk);
- cout<<"使用指向派生类的指针bks(指向基类的其他派生类对象bad_book)"<<endl;
- cout<<"不可以"<<endl;
- // good_book *bks;
- // bks = new bad_book();
- // cout<<bk->getName()<<endl;
- // delete(bk);
- cout<<"=================================================================="<<endl;
- cout<<"使用基类实例对象Obk"<<endl;
- book Obk;
- cout<<Obk.getName()<<endl;
- cout<<"使用派生类实例对象Ogood_book"<<endl;
- good_book Ogood_book;
- cout<<Ogood_book.getName()<<endl;
- cout<<"使用派生类实例对象Obad_book"<<endl;
- bad_book Obad_book;
- cout<<Obad_book.getName()<<endl;
- cin>>pause;
- return 0;
- }
编译运行程序,得出结果:
由输出结果可以知道,在两个派生类继承并覆写了基类的虚函数的情况下:
1、使用基类类型指针,那它指向哪个对象实例就会调用哪个对象的函数;
2、使用派生类类型指针,它不能指向基类和该基类的其他派生类,只能指向该派生类对象并调用该派生类对象的函数;
3、使用对象实例,那使用的是哪个对象实例就会调用哪个对象的函数。
在这里,再把该虚函数改为普通函数,即把book.h 文件的getName函数前面的virtual关键字给去掉,源代码如下:
book类的头文件:book.h
- #ifndef _BOOK_H_
- #define _BOOK_H_
- #include <string>
- using namespace std;
- class book{
- protected:
- string name;
- public:
- book();
- string getName();
- };
- #endif
再次编译运行程序,得出结果:
对照没去掉virtual关键字运行的结果可知道,唯一的区别就是——若使用基类类型指针,那不管它指向哪个对象实例都会调用基类对象的函数;