C++:

这里引用到了 http://blog.csdn.net/haoel/article/details/1948051/ 中的内容,还请提前阅读陈大神的这篇博客后在阅读本篇。

覆盖,实现多态的基础,通过虚函数表来实现,下面这个例子便是覆盖 Override

 #include<iostream>

 using namespace std;

 class Base{
public:
Base(){
cout << "Base::Base" << endl;
} virtual void f(){
cout << "Base::f" << endl;
}
}; class Derived : public Base{
public:
Derived(){
cout << "Devried::Derived" << endl;
} void f(){
cout << "Derived::f" << endl;
}
}; int main(){
Base *p = new Derived(); // Base::Base CRCL Derived::Derived
p->f(); // Derived::f
}

如果 Base类f()没有被virtual修饰,如下

 #include<iostream>

 using namespace std;

 class Base{
public:
Base(){
cout << "Base::Base" << endl;
} void f(){
cout << "Base::f" << endl;
}
}; class Derived : public Base{
public:
Derived(){
cout << "Devried::Derived" << endl;
} void f(){
cout << "Derived::f" << endl;
}
}; int main(){
Base *p = new Derived();
p->f(); // Base::f
}

如果理解了陈大神博客上那些图,应该不会对这个结果产生意外,这是我画的一个草图,并不对应于真实的内存地址情况,只是为了方便说明概念,下面一排描述的是Derived:

解析:首先p是Base类型的指针,其对于p而言其能只能按照Base类型去运算偏移地址等来访问,所以其不可能访问到Derived中的函数。也就是说父类指针的作用域只有int a , Base::f Base::g这一部分。这样就能理解了。

隐藏,父类指针的访问域是父类部分,子类虽然拥有一份父类函数的拷贝,但如果子类中存在于父类同名的函数,则调用和变量类型一致的函数(即父类变量调用父类函数,子类变量调用子类函数,同时成对方的函数被隐藏)。例:

 #include<iostream>

 using namespace std;

 class Base{

 public:
int a; Base(){
cout << "Base::Base" << endl;
} void f(float a){
cout << "Base::f" << endl;
}
}; class Derived : public Base{
public:
int d;
Derived(){
cout << "Devried::Derived" << endl;
} void f(int a){
cout << "Derived::f" << endl;
}
}; int main(){
Derived *p = new Derived();
p->f(3.14f); // Derived::f
}

这里虽然传入f的参数是float型,更适合调用Base::f,但根据同名优先调用子类的原则,实际调用为Derived::f。这就是父类同名方法被隐藏,如果指针类型为父类,则称子类方法被隐藏。

如果子类f定义为 void f() 这里对f传值就会编译不通过。

Java

覆盖,java的情况很简单,只要是子类含有和父类的同名方法,就是覆盖(无论子类的函数是否为abstract)。

public class Test {
public static void main(String[] args){
Base base = new Derived();
base.f(); // Derived::f
}
} class Base { public void f() {
System.out.println("Base::f");
}
} class Derived extends Base {
public void f() {
System.out.println("Derived::f");
}
}

隐藏,Java中也存在隐藏,不过这个隐藏和C++不太一样,子类对象引用可以调用父类的同名函数

 public class Test {
public static void main(String[] args){
Derived derived = new Derived();
derived.f(); //Derived::f
derived.f(3.14f); // Base::f
}
} class Base { public void f(float a) {
System.out.println("Base::f");
}
} class Derived extends Base {
public void f(int a) {
System.out.println("Derived::f");
}
}

再讲覆盖,C++父类函数中如果调用了自己的虚成员函数,那么由于这个虚成员函数被覆盖了,所以其实相当于调用了子类的函数。例:

#include<iostream>

using namespace std;

class Base{

public:
int a; Base(){
cout << "Base::Base" << endl;
} void f(){
g();
} virtual void g(){
cout << "Base::g" << endl;
}
}; class Derived : public Base{
public:
int d;
Derived(){
cout << "Devried::Derived" << endl;
} void g(){
cout << "Derived::g" << endl;
}
}; int main(){
Derived *p = new Derived();
p->f(); // Derived::g
}

Java中类似:

 public class Test {
public static void main(String[] args){
Base base = new Derived();
base.f(); //Derived::f
}
} class Base { public void f() {
g();
} public void g(){
System.out.println("Base::g");
}
} class Derived extends Base {
public void g(){
System.out.println("Derived::g");
}
}

由于想利用这种特性,有人会犯一个错误,在父类的构造函数中调用被覆盖的函数,由于子类在构建时先调用父类的构造函数,此时子类为构造所以不能调到子类的覆盖方法,由此

产生了奇怪的错误。

C++/Java中继承关系引发的调用关系详解的更多相关文章

  1. JAVA中的四种JSON解析方式详解

    JAVA中的四种JSON解析方式详解 我们在日常开发中少不了和JSON数据打交道,那么我们来看看JAVA中常用的JSON解析方式. 1.JSON官方 脱离框架使用 2.GSON 3.FastJSON ...

  2. java中ReentrantLock类的详细介绍(详解)

    博主如果看到请联系小白,小白记不清地址了 简介 ReentrantLock是一个可重入且独占式的锁,它具有与使用synchronized监视器锁相同的基本行为和语义,但与synchronized关键字 ...

  3. Java中的String,StringBuffer,StringBuilder详解与区别

    1.String Java中string类是不可变的,其中在声明的源代码中用的final,所以只能声明一次.所以每次在明面上的改变其实是重新生成一个String对象,指针指向新的String对象.同时 ...

  4. java中String是对象还是类?详解java中的String

    有很多人搞不懂对象和类的定义.比如说java中String到底是对象还是类呢? 有人说String 既可以说是类,也可以说是对象. 其实他这么说也没问题, 类和对象其实都是一个抽象的概念. 我们可以把 ...

  5. 线程:Java中wait、notify、notifyAll使用详解

    基础知识 首先我们需要知道,这几个都是Object对象的方法.换言之,Java中所有的对象都有这些方法. public final native void notify(); public final ...

  6. java中Timer类的详细介绍(详解)

    一.概念 定时计划任务功能在Java中主要使用的就是Timer对象,它在内部使用多线程的方式进行处理,所以它和多线程技术还是有非常大的关联的.在JDK中Timer类主要负责计划任务的功能,也就是在指定 ...

  7. java中Dateformat类的详细使用(详解)

    DateFormat其本身是一个抽象类,SimpleDateFormat 类是DateFormat类的子类,一般情况下来讲DateFormat类很少会直接使用,而都使用SimpleDateFormat ...

  8. Java中的双重检查(Double-Check)详解

    在 Effecitve Java 一书的第 48 条中提到了双重检查模式,并指出这种模式在 Java 中通常并不适用.该模式的结构如下所示: ? 1 2 3 4 5 6 7 8 9 10 public ...

  9. Java中的宏变量,宏替换详解。

    群友在微信群讨论的一个话题,有点意思,特拿出来分享一下. 首先来看下面这段程序,和群友分享的大致一样. public static void main(String[] args) { String ...

随机推荐

  1. [Z] 一些关于http服务器架构设计的资料

    开始关注这块儿,先从最基础最简单的入手.这里放一些我看过的觉得可以收藏的资料,主要是网页或博客,经典书籍之类有时间再看吧: 风格之争:Coroutine模型 vs 非阻塞/异步IO(callback)

  2. 【Oracle】Oracle数据库DATABASE LINK 的命名

    当前数据库的GLOBAL_NAMES参数设置为 TRUE,使用DATABASE LINK 时,DATABASE LINK的名称必须与被连接库的 GLOBAL_NAME一致. 而要建多个 DBLINK到 ...

  3. 「小程序JAVA实战」小程序模块之间引用(19)

    转自:https://idig8.com/2018/08/09/xiaochengxu-chuji-19/ 上一节,讲了页面引用模块的概念,如果是模块之前引用呢?源码:https://github.c ...

  4. Struts2 的核心、执行原理

    转自: http://www.cnblogs.com/xiadongqing/p/5240615.html 在学习struts2之前,首先我们要明白使用struts2的目的是什么?它能给我们带来什么样 ...

  5. AngularJS的 $resource服务 关于CRUD操作

    AngularJs 的CRUD 操作 是指对数据库的操作: CRUD其实是数据库基本操作中的Create(创建).ReadRetrieve(读取).Update(更新).Delete(删除).而这里的 ...

  6. .net core 2.0的一次奇特经历

    环境:.net core SDK版本 2.0.0-preview1-005977 VS 2017 version 15.3.0 preview 3.0 问题描述:今天在迁移Job的项目中,中午吃饭的时 ...

  7. SPI子系统分析之二:数据结构

    内核版本:3.9.5 spi_master struct spi_master用来描述一个SPI主控制器,我们一般不需要自己编写spi控制器驱动. /*结构体master代表一个SPI接口,或者叫一个 ...

  8. python操作符重载

    操作符重载的魔术方法 操作符 方法 取反 即席 + __add__ __radd__ __iadd__ - __sub__ __rsub__ __isub__ * __mul__ __rmul__ _ ...

  9. 201671010140. 2016-2017-2 《Java程序设计》java学习第十二周

    java学习第十章:图形程序设计       本章,介绍的是如何编写使用图形用户界面GUI的java程序.主要讲的是如何编写定义屏幕上的窗口大小和位置的程序,如何在窗口中采用多种字体显示文本,如何显示 ...

  10. java算法 第七届 蓝桥杯B组(题+答案) 4.分小组

    4.分小组  (代码填空) 9名运动员参加比赛,需要分3组进行预赛.有哪些分组的方案呢? 我们标记运动员为 A,B,C,... I下面的程序列出了所有的分组方法. 该程序的正常输出为:ABC DEF ...