分享
 
 
 

C++、Java和C#语言在处理“虚拟私有方法”上的差异

王朝c#·作者佚名  2006-01-31
窄屏简体版  字體: |||超大  

steedhorse(晨星)原创

运行时动态绑定被调过程的“虚拟方法”(virtual method)机制是实现多态的关键技术。C++、Java和C#(按出生年月排列,上同,下同)作为三种主流的支持对面向对象的程序设计语言,自然都提供了这种动态的方法绑定机制,在这个问题上三兄弟没有谁是含糊的。但当“虚拟”(virtual)和“私有”(private)碰在一起时,这几种语言在处理上却有所不同,本文的故事就是从一段小程序说起的:

我们来看下面这段短小的C++程序:

// Test.cpp

#include <iostream>

using namespace std;

class Base

{

public:

void f()

{

g();

}

private:

virtual void g()

{

cout << "Hi, MorningStar! I am g() of Base!." << endl;

}

};

class Derived : public Base

{

private:

virtual void g()

{

cout << "Hi, MorningStar! I am g() of Derived." << endl;

}

};

int main()

{

Base *pB = new Derived();

pB->f();

delete pB;

return 0;

}

程序很简单,我们在基类“Base”中,通过共有方法f调用了虚拟的私有方法g,而继承自Base的Derived类中覆写(override)了私有的方法g。

先不考虑其他,语法上有问题吗?没有;编译能通过吗?能。那运行结果是什么呢?既然编译能通过,那么结果也就能猜到了,应该是:

Hi, MorningStar! I am g() of Derived.

没错,VC6.0,VC.net 2003和gcc都是这个结果。从结果来看,对私有方法g的调用在运行时绑定到了对象实际类型(Derived)的方法上,这符合虚拟函数的语义。

我们知道,在Java中,没有“virtual”这么个关键字,默认就是virtual,不可被覆写才需要加关键字“final”。Java中,对任何可被覆写的方法如果想调用父类的方法,则需加特殊的关键字“super”,好了,不多说Java语法了,我们看下面一段类似的Java程序:

//Derived.java

class Base {

public void f() {

g();

}

private void g() {

System.out.println("Hi, MorningStar!, I am g() of Base.");

}

}

public class Derived extends Base {

private void g() {

System.out.println("Hi, MorningStar!, I am g() of Derived.");

}

public static void main(String[] args) {

Base b = new Derived();

b.f();

}

}

使用命令行

javac Derived.java

编译,然后

Java Derived

运行,应该不会有什么问题(偶是在Eclipse里头直接运行的:P)。结果为:

Hi, MorningStar!, I am g() of Base.

看来虽然程序类似,但结果是不一样。

翻了翻C++98标准(ISO/IEC 14882)的相关章节,没有发现任何关于此种情况的特殊描述,惟一涉及到虚拟函数访问的第11.6节:Access to virtual functions,说的又不是这种情况。由此可见,C++语言中仅仅分别规定了public,protected和private三者的访问控制问题和virtual方法的动态绑定问题,而对于他们的组合,没加任何限制,换句话说,前后是两种无关的机制,访问控制专门负责访问权限的问题,不管方法是不是虚拟;而虚拟只管延迟绑定的问题,不管公有、保护还是私有。于是,前面的C++程序输出那个结果也就不足为怪了。

然而,从面向对象的角度考虑,基类中私有的东西对外界、对继承类都是不可见的,继承类根本不应该知道基类中任何私有的东西,于是继承、覆写也应无从谈起才对,即使方法重名,那也应该仅仅看作一种巧合,Java就是这么做的。

在Java中,private天生就是final的,我想Java的设计者至少有过上面的考虑:既然是私有,就不可见,见都见不到,何谈覆写?所以,在Java中,我们讨论继承和多态都是针对类的对外接口,包括puclic方法、protected方法和默认的friendly方法,而private是不被纳入考量的,从某种意义上,Java中的private方法纯粹是为方法而方法,是一种组织代码使之更清晰,更易维护的手段而已。

但如果仅从语法语义上考虑,而不是从面向对象的理论上考虑,或许C++更厚道一些——既然没有限制,那么private也可以virtual,既然可以virtual,那也就应该享受virtual级的待遇。而Java也没什么virtual不virtual,没有任何语法痕迹便闷声地规定:public/protected/friendly的是这样,而private的是那样。

最后,让我们来看看时代的新宠,C#是怎么做的呢?我们使用Visual Studio.net 2003新建Console应用程序,添加C#源文件,然后也可以写类似的代码:

//Test.cs

using System;

namespace Test

{

class Base

{

public void f()

{

g();

}

private virtual void g()

{

Console.WriteLine("Hi, MorningStar!, I am g() of Base.");

}

}

class Derived : Base

{

private override void g()

{

Console.WriteLine("Hi, MorningStar!, I am g() of Derived.");

}

public static void Main

(String[] args)

{

Base b = new Derived();

b.f();

}

}

}

编译一下。完蛋了,编译通不过!

...\Test.cs(14): “Test.Base.g()” : 虚拟成员或抽象成员不能是私有的

...\Test.cs(22): “Test.Derived.g()” : 虚拟成员或抽象成员不能是私有的

看来还是C#够狠,语法上拒绝虚拟私有——那就没啥输出结果可以拷贝过来了。

C#从C++那里继承了“virtual”关键字,而这一点跟Java只是形式上的不同,C#中非virtual方法在很大程度上就相当于Java中的final方法。只是Java中final还用于指定类本身是否可被继承,C#使用另外一个关键字“sealed”做这件事。

总结:

C++从语法到语义上都支持可被覆写的虚拟私有成员;

Java语法上看不出什么痕迹,但语义上不存在可被覆盖的私有成员;

C#从语法上直接拒绝私有方法成为虚拟(可被覆写)。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有