依据DDJ的C/C++专栏作家Al Steven表示:他虽然不是很懂得Java﹐但是看到这些书中对于C++的物件导向概念的阐释﹐有些地方明显错误﹐真是令人担心。本文假设读者您已熟悉一些C/C++语言的概念﹐对Java也有初步的认识。而谈论Java的interface与C++的多重继承之主要异同处。
interface与多重继承的观念
不管是Java的interface或是C++的多重继承﹐在物件导向的理论里﹐都算是蛮新颖的概念。所以这里我们谈的﹐是以程式语言的角度﹐看看Java interface的所有意义与功能﹐是否C++的多重继承能全部诠释?或是相反地以Java的来诠释C++的。
首先让我们来复习一下什么是C++的多重继承。 「继承」通常在物件导向程式语言中﹐扮演着程式码的重复利用的重责大任﹐而C++的多重继承则让某一个子类别可以继承许多分属于不同资料型别的父类别如下:
#include <stdio.h>;
class Test1 {
public:
virtual void f1() {puts("Test1::f1()"); }
virtual void g1() {puts("Test1::g1()"); }
};
class Test2 {
public:
virtual void f2() { puts("Test2::f2()"); }
virtual void g2() { puts("Test2::g2()"); }
};
class Test3 : public Test1, public Test2 {
public:
virtual void gg() { puts("Test3::gg()"); }
};
void main() {
Test3 t3; t3.f1(); t3.f2();
t3.g1(); t3.g2(); t3.gg();
}
// 程式输出:
Test1::f1() Test2::f2() Test1::g1()
Test2::g2() Test3::gg()
程式1﹑C++的多重继承
根据[Rie96]﹐认为正确使用物件导向技术中之「多重继承」观念﹐应该如下面的例子:
假设有一个木造门﹐则:
1. 此木造门是门的一种(a kind of)。
2. 但门不是木造门的一部份(a part of)。
3. 木造门是木制品的一种。
4. 但木制品不是木造门的一部份。
5. 木制品不是门的一种。
6. 门也不是木制品的一种。
所以您可以发现﹐多重继承在使用时﹐必须非常小心﹐而且在许多时候﹐其实我们并不需要多重继承的。
Java也提供继承机制﹐但还另外提供一个叫interface的概念。由于Java的继承机制只能提供单一继承(就是只能继承一种父类别)﹐所以就以Java的interface来代替C++的多重继承。interface就是一种介面﹐规定欲沟通的两物件﹐其通讯该有的规范有哪些。如以Java程式语言的角度来看﹐Java的interface则表示:一些函数或资料成员﹐为另一些属于不同类别的物件所需共同拥有﹐则将这些函数与资料成员﹐定义在一个interface中﹐然后让所有不同类别的Java物件可以共同操作使用之。
所以﹐对于Java的继承与interface﹐我们总结如下:
1.Java的class只能继承一个父类别(用extends关键字)﹐但可以拥有(或称实作)许多interface(用implements关键字)。
2.Java的interface可以继承许多别的interface(也是用extends关键字)﹐但不可以实作任何interface。
因此﹐我们可以利用Java的interface来模拟C++的多重继承。如上面的例子可以转化如下:
interface Test1 {
public void f1();
public void g1();
}
interface Test2 {
public void f2();
public void g2();
}
interface Test3 extends Test1, Test2 {
public void gg();
}
class CTest implements Test3 {
public void f1() { System.out.println("Test1::f1()"); }
public void g1() { System.out.println("Test1::g1()"); }
public void f2() { System.out.println("Test2::f2()"); }
public void g2() { System.out.println("Test2::g2()"); }
public void gg() { System.out.println("Test3::gg()"); }
}
class Run {
public void run() {
CTest ct=new CTest(); ct.f1();ct.f2();
ct.g1();ct.g2(); ct.gg();
}}
class Main {
public static void main (String args[]) {
Run rr=new Run();
rr.run();
}}
// 程式输出:
Test1::f1() Test2::f2() Test1::g1()
Test2::g2() Test3::gg()
程式2﹑利用Java的interface完成C++的多重继承功能
然而﹐根据[Ait96]的文章显示﹐他认为Java的interface比C++的多重继承好学很多﹐也较容易懂﹐但是有其限制。对于Java interface的易懂﹐在文章中﹐并没有说明。其主要即为「介面继承」与「实作继承」概念的差异。
「介面继承」就是只继承父类别的函数名称﹐然后子类别一定会实作取代之。所以当我们以父类别的指标「多型」于各子类别时﹐由于子类别一定会实作父类别的多型函数﹐所以每个子类别的实作都不一样﹐此时我们(使用父类别指标的人)并不知道此多型函数到底怎么完成﹐因之称为「黑箱设计」。
「实作继承」就是继承父类别的函数名称﹐子类别在实作时﹐也会用到父类别的函数实作。所以我们(使用父类别指标的人)知道此多型函数怎么完成工作﹐因为大概也跟父类别的函数实作差不多﹐因之称为「白箱设计」。
套用的Java的interface上﹐我们发现﹐Java的interface就是介面继承﹐因为Java interface只能定义函数名称﹐无法定义函数实作﹐所以子类别必须用「implements」关键字来实作之﹐且每个实作同一介面的子类别当然彼此不知道对方如何实作﹐因此为一个黑箱设计。
Java的类别继承则为实作继承﹐子类别会用到父类别的实作(更正确地说应该是父类别有定义实作﹐所以子类别可能会使用到﹐即使不使用到也会遵循父类别实作的演算法)﹐所以父类别与子类别有一定程度的相关性﹔不像介面继承﹐彼此只有函数名字刚好一样而已。
介面继承与实作继承﹐应对至Java的interface﹑class﹑extends与implements关键字﹐很容易了解其含意。但是C++的继承机制﹐似乎就没有那么容易解释清楚的!所以这就是[Ait86]文章中所表示的意思:C++多重机制比较复杂。
所以接下来我们将讨论:
C++的多重继承有什么功能﹐是Java的interface所达不到的?
在C++的ARM中﹐或是[Str94]的多重继承章节里﹐皆提到了下述著名的例子:
#include <stdio.h>;
class t1 {
public:
virtual void f() { puts("t1::f()"); }
virtual void g() { puts("t1::g()"); }
};
class t2 : public virtual t1 {
public:
virtual void g() { puts("t2::g()"); }
};
class t3 : public virtual t1 {
public:
virtual void f() { puts("t3::f()"); }
};
class t4 : public t2, public t3, public virtual t1 { ...};
void main() {
t4 *tt4=new t4; t2 *tt2=tt4; t3 *tt3=tt4;
tt4->;f(); tt4->;g(); tt2->;f(); tt3->;g();
}
// 程式输出:
t3::f() t2::g() t3::f() t2::g()
程式3﹑C++著名的环状继承
由上例﹐我们发现﹐C++的多重继承具有下列两个特质是Java的interface所不能达到的功能。
图1﹑C++的环状多重继承
C++的多重继承可以形成环状继承关系﹐如图1。但是不管是Java的继承机制或是interface﹐都不容许有环状的情况发生。换句话说﹐因为C++有virtual base的属性的父类别﹐所有在多重继承时﹐允许父类别被继承两次以上。但Java则完全不行。
本题中的tt4指标﹐转成tt2指标后﹐执行f()函数时﹐仍然会正确地执行tt4中的f()函数﹐也就是t3::f()。我们可以发现﹐这种找函数的方式﹐是先找函数的正确名称﹐再找函数所属的类别的正确名称。与Java的虚拟函数(或称为abstract函数)不同。Java的是先找指标(或参考)所属的正确类别名称﹐再继续找类别名称下的正确函数名称。
图2﹑对于虚拟函数C++与Java的各别作法
对于第二点参考图2。C++的虚拟函数﹐可以参考[Sou94]﹐C++编译器对于每一个虚拟函数﹐均建立一个虚拟函数表与之应对﹐因为每一个虚拟函数在一个继承树可能有许多子类别实作之。因此在实际执行时﹐是先找虚拟函数表﹐然后再寻找与自己类别阶层等级最靠近的那个函数实作。所以我们可以将一个父类别指标转换成子类别后﹐反而仍执行母亲那辈的虚拟函数。
而Java则不能透过interface执行上述功能。Java的抽象函数(abstract function)事实上就是C++的纯虚拟函数(virtual function()=0)﹐没有像C++可以有非纯虚拟函数(就是子类别不一定要定义的虚拟函数)﹐所以很难执行上面复杂的例子。并且﹐Java的interface里的函数预设为抽象函数﹐也就是如果某类别实作此interface的话﹐interface里的所有函数都必须全部实作。因此在实际执行时﹐先决定interface物件转型成某类别的物件﹐于是再执行该类别内的函数实作。
乍看之下﹐似乎C++的多重继承功能较完整﹐那么:
Java的interface概念﹐是否可用C++的多重继承模拟出来呢?
目前﹐在微软的OLE技术中﹐确实是用C++的多重继承模拟OLE中的interface概念﹐可以参考MFC中关于OLE COM的写作。如下面的程式:
class CoSomeObject : public Iunknown, public Ipersiet {
// IUnknown methods
virtual DWORD AddRef(void);
virtual DWORD Release(void);
virtual HRESULT QueryInterface(REFILD, LPVOID FAR*);
//IPersist methods
virtual HRESULT GetCLASSID(LPCLSID pclsid);
};
(注:参见MFC Internals p.p 442)
然而﹐考虑以下的问题:Java interface的特色为﹐interface间可以继承。但这里所谓的继承﹐事实上只是子interface包括全部的父interface内的成员﹐无法像Java的类别或是C++的类别那样﹐可以用子类别的新定义将父类别取代之。这也就是所谓的「介面继承」与「实作继承」的差别。换言之﹐Java interface继承(注意﹐不是子类别implements父interface)只是一种「包含关系」而已﹐甚至包含不可以重复。所以﹐interface概念用在软体模组间的介面定义便非常厉害﹐如CORBA的IDL便是。因此﹐Java interface仍然拥有许多优点﹐但如果我们要以C++的多重继承模拟(或称之为藉此学习Java interface概念)时﹐在C++这边该如何映对呢?
我们以程式2的Java程式为主﹐观察C++的模拟interface版﹐该如何映对。
#include <stdio.h>;
class Test1 {
public:
virtual void f1()=0;
virtual void g1()=0;
};
class Test2 {
public:
virtual void f2()=0;
virtual void g2()=0;
};
class Test3 : public Test1, public Test2 {
public:
virtual void gg()=0;
};
class CTest : public Test3 {
public:
void f1() { puts("Test1::f1()"); }
void g1() { puts("Test1::g1()"); }
void f2() { puts("Test2::f2()"); }
void g2() { puts("Test2::g2()"); }
void gg() { puts("Test3::gg()"); }
};
void main() {
CTest ct; ct.f1();ct.f2();
ct.g1();ct.g2(); ct.gg();
}
// 程式输出:
Test1::f1() Test2::f2() Test1::g1()
Test2::g2() Test3::gg()
程式4﹑C++对应的Java interface概念
由程式4可知﹐其实只要在每个类别中的每一个函数都宣告成纯虚拟函数﹐则C++类别就变成Java interface概念了。
因此我们下一结论:C++的多重继承功能较广﹐Java的interface功能只是其中的一个子集。因为C++的虚拟函数可以有纯虚拟函数﹐也可有非纯虚拟函数﹐而Java只有抽象函数﹐所以功能模式少一种﹐自然能达到的效果较少一些。
但这并不代表Java的interface就比较差﹐因为interface的观念较简单﹐全部动态的抽象函数也正代表着Java为一纯物件导向语言。与C++不同的是﹐C++考虑许多执行效率的问题﹐所以语言本身就变的较复杂化﹐同时C++的编译器也是公认难写的﹐多重继承更是一大挑战。Java的interface虽然好象少了一些功能﹐但其实那些功能在一般的程式设计中也很少碰到﹔并且观念简洁的Java interface﹐在设计软体程式时更可以避免许多陷阱。总之﹐两种程式语言机制是很难比较谁好谁坏的。
顺带一提的是:最近有一股新趋势﹐就是物件导向程式语言所引导出来的新的概念﹐反过来引响物件导向分析与设计的基础理论。如Java的interface或是微软的OLE Interface﹐使得Booch﹑OMT整合方法&shy;&shy;UML﹐对软体模组间的介面有了新的定义﹔或是C++的STL与template﹐促进许多学者对静态的物件关系又有了新解等。■
参考资料
[Ait96]Aitken, Gary. (1996) Moving from C++ to Java, Dr.Dobb’s Journal, Vol.21, Issue 3, A Miller Freeman Publication.
[Fla96]Flanagan, David. (1996) Java in a Nutshell, O’Reilly.
[Mor+96]Morrison, Michael. et al. (1996) Java Unleashed., Sams.
[Rie96]Reil, Arthur. (1996) Object-Oriented Design Heuristics, Addison-Wesley.
[[Str94]Stroustrup, Bjarne. (1994) The Design and Evolution of C++, Addison-Wesley.
文章来自 http://www.umlchina.com
相关推荐
Java的interface观念与C++多重继承比较
C++的多重继承功能较广,Java的interface功能只是其中的一个子集。因为C++的虚拟函数可以有纯虚拟函数,也可有非纯虚拟函数,而Java只有抽象函数,所以功能模式少一种,自然能达到的效果较少一些。 但这并不代表Java的interface就比较差,因为interface的观念较简单,全部动态的抽象函数也正代表着Java为一纯物件导向语言。与C++不同的是,C++考虑许多执行效率的问题,所以语言本身就变的较复杂化,同时C++的编译器也是公认难写的,多重继承更是一大挑战。
java的接口和C++的虚类的相同和不同处
Java的接口(Interface)和C++的虚类(Virtual Class,尽管通常我们不直接使用“虚类”这个术语,而是说包含虚函数的类)在面向对象编程中都有重要的用途,但它们之间确实存在一些相同点和不同点。Java的接口不能有数据成员(从Java 8开始,接口可以包含静态常量)和非抽象方法(从Java 8开始,接口可以包含默认方法和静态方法,但它们不是真正的实例方法)。Java的接口是一个完全抽象的类,它只包含抽象方法和常量(从Java 8开始,接口也可以包含默认方法和静态方法)。
VirtualBox增强功能安装全指南:从下载到配置复制粘贴功能
本文详细介绍了VirtualBox增强功能的完整安装与配置流程,重点解决了虚拟机与主机间复制粘贴、文件拖放等核心协作难题。通过分步指南和故障排查,帮助用户在不同操作系统(如Windows、Linux)中实现无缝集成,提升虚拟化工作效率与体验。
java中的接口用C++怎么理解
看设计模式时,书中以java举例,其中使用了java的接口,但本人却是C++选手,对java也不了解,故此文来学习理解。
ESD镜像解密与转换全攻略:从esd-decrypter到WinNTSetup的完整流程
本文详细解析了ESD镜像的加密特性与压缩优势,并提供了从解密到转换的完整实战指南。核心步骤包括使用esd-decrypter工具解密ESD文件为WIM格式,以及如何结合WinNTSetup进行灵活的系统安装或进一步封装为可引导的ISO镜像,帮助用户高效处理官方Windows安装镜像。
服务器卡死排查实战:从现象分类到根因定位的完整手册
服务器卡死是运维中最令人头疼的故障之一,从游戏圈吐槽的“土豆服务器”到生产环境中的Linux系统无响应、rsync复制挂起,本质都是系统或进程失去正常响应能力。其原理通常涉及CPU、内存、磁盘IO或网络资源耗尽,以及内核和驱动异常。掌握系统化的排查方法,能够帮助工程师快速定位根因、缩短故障时间,避免盲目重启。本文从资源、层级、场景等多维度分类,结合top、dmesg、strace等工具,梳理一套从现象确认、指标收集、日志分析到进程定位的实战排查流程,并覆盖常见高频场景与预防治理建议。无论你是运维新手还是老手
C++接口实现总结
网上的例子,稍微有点错误。我给更改一下,附件上有源码!如有错误,请指正。 总结一下C++实现接口的技巧。 面向对象的语言诸如JAVA提供了Interface来实现接口,但C++却没有这样一个东西,尽管C++ 通过纯虚基类实现接口,譬如COM的C++实现就是通过纯虚基类实现的(当然MFC的COM实现用了嵌套类),但我们更愿意看到一个诸如 Interface的东西。下面就介绍一种解决办...
GEO芯片数据下载和探针ID转换(保姆级教程)
R语言安装、GEO芯片数据下载、探针ID转换
JAVA的Interface观念与C++多重继承的比较
Interface与多重继承的观念 不管是Java的Interface或是C++的多重继承,在物件导向的理论里,都算是蛮新颖的概念。所以这里我们谈的是以程序语言的角度看看Java Interface的所有意义与功能,C++的多重继承是否能全部诠释?或是相反地以Java的来诠释C++的。 首先让我们来复习一下什么是C++的多重继承。 「继承」通常在物件导向程序语言中,...
Zemax实战:手把手教你设计一个40倍、NA0.65的显微物镜(附初始结构文件)
本文详细介绍了使用Zemax设计40倍、NA0.65显微物镜的完整流程,从初始结构搭建到优化验证,涵盖光学设计的关键技巧和实战经验。通过分阶段优化策略和公差分析,帮助工程师快速掌握高倍显微物镜的设计方法,提升光学系统性能。
【校招】SHL 的 General Ability (GA, 通用能力测试)
SHL 的 General Ability (GA, 通用能力测试) 文章目录SHL 的 General Ability (GA, 通用能力测试)1、归纳推理题1.1 圈圈线条推理1.2 图形颜色位置推理1.3 箭头指向推理2. 数字推理题攻略3. 语言推理题 1、归纳推理题 归纳推理题我把它总结为三种类型:圈圈线条推理;图形颜色位置推理;箭头指向推理。 1.1 圈圈线条推理 你别看这个题目看起来很复杂,其实很简单,而且这个题型的题目背后原理都一样!我把我的 tips 偷偷分享给你们嘿嘿~先从 A
Interface进化历程 --Java中Interface与C++中相关概念的点点理解
Java中Interface与C++中相关概念的点点理解 今天查Tuple这个词在编程中的意义时不经意间看到了C++中头文件声明这个说法,好长时间没写C++代码了,现在把C++的头文件放到Java的语境里不由自主地就想到了Java中Interface的概念. 表面上有点像. 1,以"实现"角度来看,在Java中一个接口得有实现类不然没有实际意义;C++中,一个...
ABAP - Function ALV 11 - 单元格下拉框
【代码】ABAP - Function ALV 11 - 单元格下拉框。
JAVA的interface观念与C++多重继承的比较
JAVA的interface观念与C++多重继承的比较 interface与多重继承的观念 不管是Java的interface或是C++的多重继承﹐在物件导向的理论里﹐都算是蛮新颖的概念。所以这里我们谈的﹐是以程式语言的角度﹐看看Java interface的所有意义与功能﹐是否C++的多重继承能全部诠释?或是相反地以Java的来诠释C++的。首先让我们来复习一下什么是C++的多重继承。 「继承」
【新版系统架构】系统架构设计师教程全篇知识点提炼
信息系统的5个基本功能:输入、存储、处理、输出和控制信息系统的发展:诺兰模型:初始阶段、传播阶段、控制阶段、集成阶段、数据管理阶段、成熟阶段信息系统的分类:传统的信息系统分为:业务(数据)处理系统、管理信息系统(MIS)、决策支持系统(DSS)、专家系统(ES)、办公自动化系统(OAS)等5类信息系统的生命周期:1、产生阶段2、开发阶段(总体规划、系统分析、系统设计、系统实施、系统验收阶段)3、运行阶段4、消亡阶段信息系统建设原则:1、高层管理人员介入原则。
lwip-2.0.3
lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。
多重继承_谈一下interface,mixin,与多重继承
前言redis系列先鸽一次。最近厂里招人,帮着面了一部分后端候选人。当面试者表示熟悉python的时候,有一个考察角度是从mixin设计模式开场,视程度逐步深入到py中经典类与新式类、多重继承、最后是C3算法的一些讨论。心痒梳理一下,只是泛泛的谈一下心得,欢迎各位大佬批评指正,共同学习。interfaceinterface 是java 里较为基础的概念。面向接口编程也是老生常谈了。ja...
WINCC7.3破解文件
WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!
c++中能否使用interface(如java)那样的功能?
问: 确认一下c++中不能使用interface(如java)那样的功能把我认为是不能的,注意我说的是interface(用于java多重继承的那个,不是一般意义的接口)我觉得是没有的,但是网上搜索说什么的都有而且人还不少…… 所以希望大家能给我一个明确的答复好么?最好能还有一些解释啦 ^_^ 答: 想比较语言, 请首先熟悉两门语言。java的interface
假人有限元模型
假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用
VC中sqlite的使用
在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示
java的"多重继承":interface模拟
java的多重继承~interface模拟 interface与多重继承的观念不管是Java的interface或是C++的多重继承﹐在物件导向的理论里﹐都算是蛮新颖的概念。所以这里我们谈的﹐是以程式语言的角度﹐看看Java interface的所有意义与功能﹐是否C++的多重继承能全部诠释?或是相反地以Java的来诠释C++的。首先让我们来复习一下什么是C++的多重继承。「继承」通常在
java语言支持多继承_Java 8 -- 事实上的多继承语言
Java 在多重继承上的设计甚至不如 C++。这个论点让人很难接受,毕竟我们在第一堂 Java 课上学到了:“Java 的优越性之一是摒除了 C++ 中易出错的多重继承”。然而,Java 的类单继承、接口多继承的设计,最终使 Java 走上了多重继承的老路,这最后一根稻草就是 Java 8 的 default关键字。Java 为什么设计成单继承Java 语言在设计之初显然受到了 C++ ...
java多重继承_java 中的多重继承
Java中的接口不仅仅是一种更纯粹的抽象类,它的目标比这更高。因为接口是根本没有任具体实现的。也就是说,没有任何与接口相关的存储;因此,也就无法阻止多个接口的组合。这一点是很有价值的,因为你有时候需要去表示“一个X是一个a和一个b以及一个c”。在C++中,组合多个类的接口的行为被称作为多重继承。它可能会使你背负很沉重的包袱,因为每个类都有一个具体实现。在java中,你可以执行相同的行为,但是只有一...
java的多重继承~interface模拟
interface与多重继承的观念 不管是Java的interface或是C++的多重继承﹐在物件导向的理论里﹐都算是蛮新颖的概念。所以这里我们谈的﹐是以程式语言的角度﹐看看Java interface的所有意义与功能﹐是否C++的多重继承能全部诠释?或是相反地以Java的来诠释C++的。 首先让我们来复习一下什么是C++的多重继承。 「继承」通常在物件导向程式语言中﹐扮演着程式码的重复利
java抽象类可以多继承吗_Java 8: 事实上的多继承语言
Java 在多重继承上的设计甚至不如 C++。这个论点让人很难接受,毕竟我们在第一堂 Java 课上学到了:“Java 的优越性之一是摒除了 C++ 中易出错的多重继承”。然而,Java 的类单继承、接口多继承的设计,最终使 Java 走上了多重继承的老路,这最后一根稻草就是 Java 8 的 default 关键字。Java 为什么设计成单继承Java 语言在设计之初显然受到了 C++ 的很大影...
C++多重继承与钻石继承:二义性、内存布局与工程实践指南
在C++面向对象编程中,继承是实现代码复用的核心机制。多重继承允许一个类从多个基类派生,但这也引入了复杂的名称查找与二义性问题。其技术价值在于能够组合多个类的功能,实现更灵活的设计,例如模拟现实世界中的多重角色。然而,当多个基类拥有同名成员时,编译器无法确定具体调用哪个版本,导致访问歧义。在更复杂的钻石继承场景中,同一基类在派生类中存在多份副本,引发数据冗余与不一致。为解决这些问题,C++提供了虚继承机制,通过虚基类指针和虚基类表确保共享基类子对象唯一,但会带来额外的空间与时间开销。在实际工程中,应优先考虑
905



被折叠的 条评论
为什么被折叠?



