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
- #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关键字运行的结果可知道,唯一的区别就是——若使用基类类型指针,那不管它指向哪个对象实例都会调用基类对象的函数;
C++关键字之virtual的更多相关文章
- 浅析c++中virtual关键字
http://blog.csdn.net/djh512/article/details/8973606 1.virtual关键字主要是什么作用? c++中的函数调用默认不适用动态绑定.要触发动态绑定, ...
- C#的New关键字的几种用法
一.在C#中,new这个关键字使用频率非常高,主要有3个功能: a) 作为运算符用来创建一个对象和调用构造函数. b) 作为修饰符. c) 用于在泛型声明中约束可能用作类型参 ...
- .NET 关键字
一.base关键字 可以通过base关键字访问上一级父类方法的访问.静态static函数无法调用base 二.new 关键字new new有2个作用. new运算符 用来分配内存空间和初始化对象. ...
- C# 部分关键字
关键字: virtual: 虚方法,本身可以被实例化,也可以在派生类中重写该方法: override:在派生类重写基类虚方法时声明,避免了C++中的潜在运行错误: abstract:声明为抽象类.抽 ...
- c#和java中的方法覆盖——virtual、override、new
多态和覆盖 多态是面向对象编程中最为重要的概念之一,而覆盖又是体现多态最重要的方面.对于像c#和java这样的面向对象编程的语言来说,实现了在编译时只检查接口是否具备,而不需关心最终的实现,即最终的实 ...
- Asp.Net中virtual、override理解
virtual关键字用于指定属性或方法在派生类中重写.默认情况下,派生类从其基类继承属性和方法,如果继承的属性或方法需要在派生类中有不同的行为,则可以重写它,即可以在派生类中定义该属性或方法的新实现, ...
- Delphi 方法:overload、override、virtual、dynamic、abstract
1.overload 在Pascal语法规则中,同一个UNIT里是不能存在两个同名的函数的,例如: function func(): Boolean; function func(const x: C ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(59)-BLL层重构
系列目录 前言: 这应该是本系统最后一次重构,将重构BLL层和Model层.来完全取代代码生成器生成的BLL层和DAL层.完全废掉了代码生成器的DAL,BLL,MODEL层. 全自动生成增,删,改 ...
- Atitit 延迟绑定架构法attilax总结
Atitit 延迟绑定架构法attilax总结 配置文件的延迟绑定1 Api属性与方法的回调延迟绑定1 后期绑定和前期绑定2 延迟调用2 用 Java 语言延迟绑定2 什么是推迟绑定 C++3 配置文 ...
随机推荐
- Java 基本语法---Java方法
Java 基本语法---Java方法 0.概述 方法:就是用来解决一类问题的代码的有序组合,是一个功能模块: 在方法部分,只使用对象名词调用方法: Scanner sc = new Scanner(S ...
- java innerclasses(内部类)
可以将一个类定义在另一个类的内部,这就是内部类 创建内部类的方式---把类的定义置于外部类的里面 典型的情况是,外部类将有一个方法,该方法返回一个指向内部类的引用,就像在to()和contents() ...
- 20165330《网络对抗技术》Exp0 Kali安装
Kali安装 下载地址 Kali官网 VMware 安装步骤 参考在虚拟机中安装kali linux 安装Kali Linux的镜像和VMware 打开VMware,选择文件-新建虚拟机,出现对话框选 ...
- Java编程的逻辑 (67) - 线程的基本协作机制 (上)
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...
- 翻译 – 从心理学角度看UX设计
本文是一篇非常不错的关于用户体验设计的文章,本文作者是一个心理学家,他从他所研究的领域去看到用户行为,用户体验,相信会给你带来不一样的观念与知识.翻译水平有限,若有不准确之处欢迎指正. ——————— ...
- linux操作系统语言更改
有时候我们的服务器在安装时安装的默认语言不支持中文,导致程序.文档中的汉子显示乱码,从而使系统报一些莫名其妙的错误,这是可以更改操作系统的默认语言 1.echo $LANG 查看当前操作系统的语 ...
- Could not resolve com.android.support:appcompat-v7:28.0.0 错误处理
20181008 总是出现错误 Could not resolve com.android.support:appcompat-v7:28.0.0 1.先是怀疑前些天降级了jdk 1.8 ,所以重 ...
- 解决 Could not resolve com.android.tools.build:gradle:3.1.3
android studio 升级到3.1.3后总会遇到莫名其妙的错误,前几天刚解决了项目 dependencies报错的问题. 解决android studio 升级到3.0+之后 项目 dep ...
- 大数据技术之_16_Scala学习_02_变量
第二章 变量2.1 变量是程序的基本组成单位2.2 Scala 变量的介绍2.2.1 概念2.2.2 Scala 变量使用的基本步骤2.3 Scala 变量的基本使用2.4 Scala 变量使用说明2 ...
- 7.30 正睿暑期集训营 A班训练赛
目录 2018.7.30 正睿暑期集训营 A班训练赛 T1 A.蔡老板分果子(Hash) T2 B.蔡老板送外卖(并查集 最小生成树) T3 C.蔡老板学数学(DP NTT) 考试代码 T2 T3 2 ...