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. #include <string>
  4. using namespace std;
  5. class  book{
  6. protected:
  7. string name;
  8. public:
  9. book();
  10. virtual string getName();
  11. };
  12. #endif

book类的源文件:book.cpp

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

good_book类的头文件:good_book.h

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

good_book类的源文件:good_book.cpp

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

bad_book类的头文件:bad_book.h

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

bad_book类的源文件:bad_book.cpp

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

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

场景文件:main.cpp

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

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

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

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

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

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

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

book类的头文件:book.h

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

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

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

C++关键字之virtual的更多相关文章

  1. 浅析c++中virtual关键字

    http://blog.csdn.net/djh512/article/details/8973606 1.virtual关键字主要是什么作用? c++中的函数调用默认不适用动态绑定.要触发动态绑定, ...

  2. C#的New关键字的几种用法

    一.在C#中,new这个关键字使用频率非常高,主要有3个功能: a)     作为运算符用来创建一个对象和调用构造函数. b)     作为修饰符. c)      用于在泛型声明中约束可能用作类型参 ...

  3. .NET 关键字

    一.base关键字 可以通过base关键字访问上一级父类方法的访问.静态static函数无法调用base 二.new 关键字new new有2个作用. new运算符   用来分配内存空间和初始化对象. ...

  4. C# 部分关键字

    关键字: virtual:  虚方法,本身可以被实例化,也可以在派生类中重写该方法: override:在派生类重写基类虚方法时声明,避免了C++中的潜在运行错误: abstract:声明为抽象类.抽 ...

  5. c#和java中的方法覆盖——virtual、override、new

    多态和覆盖 多态是面向对象编程中最为重要的概念之一,而覆盖又是体现多态最重要的方面.对于像c#和java这样的面向对象编程的语言来说,实现了在编译时只检查接口是否具备,而不需关心最终的实现,即最终的实 ...

  6. Asp.Net中virtual、override理解

    virtual关键字用于指定属性或方法在派生类中重写.默认情况下,派生类从其基类继承属性和方法,如果继承的属性或方法需要在派生类中有不同的行为,则可以重写它,即可以在派生类中定义该属性或方法的新实现, ...

  7. Delphi 方法:overload、override、virtual、dynamic、abstract

    1.overload 在Pascal语法规则中,同一个UNIT里是不能存在两个同名的函数的,例如: function func(): Boolean; function func(const x: C ...

  8. ASP.NET MVC5+EF6+EasyUI 后台管理系统(59)-BLL层重构

    系列目录 前言:  这应该是本系统最后一次重构,将重构BLL层和Model层.来完全取代代码生成器生成的BLL层和DAL层.完全废掉了代码生成器的DAL,BLL,MODEL层.  全自动生成增,删,改 ...

  9. Atitit 延迟绑定架构法attilax总结

    Atitit 延迟绑定架构法attilax总结 配置文件的延迟绑定1 Api属性与方法的回调延迟绑定1 后期绑定和前期绑定2 延迟调用2 用 Java 语言延迟绑定2 什么是推迟绑定 C++3 配置文 ...

随机推荐

  1. 动态规划(dp)专题

    航线设置   问题描述在美丽的莱茵河畔,每边都分布着N个城市,两边的城市都是唯一对应的友好城市,现需要在友好城市间开通航线以加强往来,但因为莱茵河常年大雾,如果开设的航线发生交叉就有可能出现碰船的现象 ...

  2. SqlServer 批量备份

    -- 实现方式1:使用游标 DECLARE @FileName VARCHAR(200), @CurrentTime VARCHAR(50), @DBName VARCHAR(100), @SQL V ...

  3. 【LOJ】#2546. 「JSOI2018」潜入行动

    题解 dp[i][j][0/1][0/1]表示以\(i\)为根的子树,用了\(j\)个,i点选了或者没选,i点被覆盖或没被覆盖 转移比较显然,但是复杂度感觉不太对? 其实转移到100个的时候就使第二维 ...

  4. Eclipse 之开发环境的常用配置

    一.Java智能提示 (1). 打开Eclipse,选择打开" Window - Preferences". (2). 在目录树上选择"Java-Editor-Conte ...

  5. 转:Spring中事物管理

    1.什么是事务? 事务是逻辑上的一组操作,这组操作要么全部成功,要么全部失败 2.事物具有四大特性ACID 说到事务,就不得不说其4大特性,主要如下 原子性:(atomicity) 原子性指的是事务是 ...

  6. 应用Mongoose开发MongoDB(3)控制器(controllers)

    控制器的基本构成与如何通过路由调用 控制器中通过建立函数并导出,实现前端对数据库的查询.新建.删除与修改的需求,并使之可以在路由中调用,完成API的封装.本文着重于结构之间的关系,具体问题解决方法将在 ...

  7. JVM简介堆中新生代老年代浅析

    一.JVM内存结构由程序计数器.堆.栈.本地方法栈.方法区等部分组成.1)程序计数器 几乎不占有内存.用于取下一条执行的指令.2)堆 所有通过new创建的对象的内存都在堆中分配,其大小可以通过-Xmx ...

  8. Git的一些常用命令

    一:Git是什么? Git是目前世界上最先进的分布式版本控制系统. 简单的说就是托管代码的便于多人开发的管理系统. 二.Git的一些命令,我详细的说一下 我是基于github给大家说一下git的一些常 ...

  9. python集合相关操作

    集合相关操作 集合是一个无序的,不重复的数据组合,它有着两个主要作用:去重以及关系测试. 去重指的是当把一个列表变成了集合,其中重复的内容就自动的被去掉了 关系测试指的是,测试两组数据之间的交集.差集 ...

  10. 1295 N皇后问题

    题目描述 Description 在n×n格的棋盘上放置彼此不受攻击的n个皇后.按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子.n后问题等价于再n×n的棋盘上放置n个皇后,任 ...