日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > C# >内容正文

C#

让我们来比较C#,C++和Java之间重写虚函数的区别

發(fā)布時(shí)間:2025/3/15 C# 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 让我们来比较C#,C++和Java之间重写虚函数的区别 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

這篇文章比較了C++,C#和Java在面向?qū)ο笾械睦^承和函數(shù)重寫的不同。

介紹


我一直用三種不同的面向?qū)ο蟮恼Z言,這三種語言都很明顯的支持繼承和遲綁定或者虛函數(shù)。我認(rèn)為一篇好的文章當(dāng)我在用Java,c#和C++中切換時(shí)他們在語法和內(nèi)定行為的不同地方會(huì)提醒我。


背景


我不斷的在切換用C++寫霜凍視頻游戲引擎和用C#寫工具和網(wǎng)頁服務(wù)器。我也用Java寫我的安卓主要的項(xiàng)目(最新的一個(gè)是群集智能的螞蟻巢穴模擬器-敬請期待)

同樣我認(rèn)為我要給自己做筆記,在繼承、函數(shù)重寫(虛函數(shù))使用三種不同的語言直接的主要區(qū)別。


使用代碼


可接入性

C++支持共有,保護(hù),和私有繼承。但是無論它做了什么,不要忘了任何的私有成員總是私有的,不能變?yōu)榭山尤氲臑槿魏位A(chǔ)或派生類調(diào)用。

?

Java簡化了繼承并且只允許共有繼承。

?

C#在這個(gè)方面仿照了Java。

?

大家都普遍同意在面向?qū)ο笳Z言中通過封裝和其他功能可實(shí)現(xiàn)保護(hù)和私有繼承,不需要這些其他復(fù)制的置換。


多繼承


現(xiàn)在我們來將一點(diǎn)關(guān)于多繼承。當(dāng)建立了一個(gè)類的層級時(shí),C++只用冒號繼承,緊隨其后的是逗號,用來分開其他基類列表。C++是唯一一個(gè)支持多繼承的語言,如果你一不小心那將會(huì)出現(xiàn)像致命的死亡菱形(DDD)結(jié)構(gòu)這種事情。總體來說,命的死亡菱形(DDD)是一個(gè)設(shè)計(jì),這個(gè)設(shè)計(jì)是多個(gè)同一類是對象的一部分實(shí)例。設(shè)想一個(gè)類叫Dog,這個(gè)Dog繼承了Animal和Pet,并且這個(gè)Animal和Pet都繼承了一個(gè)叫Printable的類,狗這個(gè)實(shí)例現(xiàn)在有兩個(gè)叫Printable的基類的實(shí)例。當(dāng)你在Dog這個(gè)類里面改變了這個(gè)Printable類的屬性后會(huì)發(fā)生什么呢?它是否會(huì)改變實(shí)例1或?qū)嵗?的屬性呢?等等等。為了避免繼承里面這種復(fù)雜的問題(無論如何,我們通常喜歡類的組合勝過繼承-組合展開是一個(gè)原因),C#和Java兩者都不支持多繼承。


接口


多年前,C++還是這個(gè)編程大陸的王者時(shí),你可能會(huì)用抽象類(一個(gè)不能被實(shí)例化的類,而且最少包含了一個(gè)純虛函數(shù))并且要把所有的純虛函數(shù)定義為一種格式也就是=0。這就意味著你需要在派生類中實(shí)現(xiàn)這些功能。這樣就誕生了接口這個(gè)定義。在C#和Java中你能操作接口,從而給你類似與多繼承的一種協(xié)定(或者你必須執(zhí)行函數(shù)簽名)

?

C#不僅支持接口(類似與C++里面的抽象類,類中包含了索引的純虛函數(shù))還支持帶有一個(gè)或多個(gè)存虛函數(shù)的抽象類,并且這些函數(shù)是帶有某種真實(shí)的功能。記住接口和抽象類里的函數(shù)必須是公用,這樣就可以在調(diào)用類的時(shí)候?qū)λ麄冞M(jìn)行直接訪問,在接口里面定義私有函數(shù)往往沒有太多意義,誰又能調(diào)用它呢?抽象類中這個(gè)類是不能調(diào)用他自己的函數(shù),這是沒有意義的!所以,C#涵蓋了抽象類、接口和具體類這三種。

?

讓我們來看這些用三種編程語言,帶有繼承和接口聲明類的代碼。


C++

class derived : public base, base2 //C++ class definition with 2 public inherited classes


Java

class Derived extends Base implements printable // new derived class that derives from base, and implements the printable contract
C# public interface printable //A contract interface public abstract class baser //A class with one or more abstact functions public class derived : baser, printable //A derived class from baser, it implements the printable interface

虛函數(shù)


面向?qū)ο蟮牧硪粋€(gè)方面是多態(tài)。這種方法是一種是在運(yùn)行是構(gòu)建的,在編譯類型時(shí)我們只知道它的層次結(jié)構(gòu),舉一個(gè)繼承中衍生類的例子,我們有一個(gè)基類型的指針。使用遲綁定調(diào)用這個(gè)函數(shù),這個(gè)函數(shù)是在運(yùn)行中被判斷而不是編譯時(shí)。這三種語言都支持遲綁定這就是虛函數(shù)。


C++

有一個(gè)老舊的思想是默認(rèn)把這個(gè)函數(shù)設(shè)置為非純虛函數(shù)。正如待會(huì)我說的那樣,如果你有一個(gè)基類和一個(gè)派生類,他們倆都有一個(gè)叫print()的函數(shù),你實(shí)構(gòu)建哪種類的實(shí)例都沒有關(guān)系,你將在類上調(diào)用函數(shù)這取決你引用或者指針是什么類型,如果你不知道你指向的是什么。用虛函數(shù),你一定要聲明虛函數(shù)(這種層次結(jié)構(gòu)在哪都是非常好的),這是告訴編譯器創(chuàng)建一個(gè)虛函數(shù)表,當(dāng)運(yùn)行是你要查找函數(shù)的地址就會(huì)依賴這張表里面。一旦函數(shù)被標(biāo)記成虛函數(shù),實(shí)例將會(huì)判決到哪調(diào)用你的函數(shù),不再依賴于引用和指針。

Java

Java一項(xiàng)都超級簡單,所有的函數(shù)都是虛函數(shù),不需要任何陳述去告訴運(yùn)行引擎那些是虛函數(shù),如果一個(gè)派生類和基類都聲明了一個(gè)叫print的函數(shù),都具有同樣的簽名,那么實(shí)例將依賴JRE的決定。超級簡單!除非你不想要這個(gè)功能(也許安全是個(gè)令人擔(dān)憂的問題比如你不想函數(shù)void?AddMoneyToBankAccount()被重寫),在這種情況下你要標(biāo)記它為常函數(shù),并且不要想著去重寫它!艸!


C#

最后是C#,在C#這里所有函數(shù)默認(rèn)都是非虛函數(shù),不僅僅是這樣,如果你想去重寫一個(gè)函數(shù),你得這個(gè)在基類上打上虛函數(shù)這個(gè)標(biāo)簽,并且重新時(shí)也要打上這個(gè)前綴標(biāo)簽。你可以做到的,然而,有兩個(gè)相同簽名的函數(shù),在繼承關(guān)系里面,并且他們并不是被重寫的關(guān)系,你要給派生類的那個(gè)函數(shù)打上“new”?這個(gè)標(biāo)簽。你要明確的告訴編譯器,我是故意這么做的。你想隱藏基類函數(shù)的功能,并且這不是虛函數(shù)。但是如果你調(diào)用函數(shù)用的是基類的指針,它將總是調(diào)用基類的函數(shù),即使你指向一個(gè)派生類的指針,你所看的這樣的功能是編譯器靜態(tài)鏈接時(shí)做的,運(yùn)行時(shí)是動(dòng)態(tài)的(盡管沒有專門的C#編譯器)

?

最后一些代碼來說明所有的虛函數(shù)和函數(shù)重寫!!


C++ Code

#include "stdafx.h" #include <iostream>using namespace std;class base {public:void hello(){cout << "Base func non-virtual" << endl;}virtual void hello2(){cout <<"Base func virtual"<<endl;} };class derived : public base //C++ class definition with 2 inherited classes { public:void hello(){cout << "Derived func non-virtual" << endl;}virtual void hello2(){cout <<"Derived func virtual"<<endl;}};int main() {cout << "calling function defined in both base and der that is NOT virtual, then calling a function that is virtual" << endl;{cout << "Instance is Derived - Reference is Derived" << endl;derived d;d.hello();d.hello2();}{cout << "Instance is Derived - Reference is Base" << endl;base *f = new derived ;f->hello();f->hello2();}{cout << "Instance is Base - Reference is Base" << endl;base t;t.hello();t.hello2();}{cout << "Instance is Derived - reinterpret cast to base - Reference is Derived" << endl;derived *g = new derived ;base *j = reinterpret_cast<base*>(g);j->hello();j->hello2();}getchar();return 0; } And the output:
calling function defined in both base and der that is NOT virtual, then calling a function that is virtual Instance is Derived - Reference is Derived Derived func non-virtual Derived func virtual Instance is Derived - Reference is Base Base func non-virtual Derived func virtual Instance is Base - Reference is Base Base func non-virtual Base func virtual Instance is Derived - reinterpret cast to base - Reference is Derived Base func non-virtual Derived func virtual

And C#

using System;namespace ConsoleApplication2 {public class based{public void hello(){Console.WriteLine("hello on base instance - non virtual on base");Console.WriteLine("func is - non virtual on deriv");}public virtual void hello2(){Console.WriteLine("hello2 on base instance - virtual on base");Console.WriteLine("func is - virtual on deriv");}public void hello3(){Console.WriteLine("hello3 on base instance - non virtual on base");Console.WriteLine("func is new and virtual on deriv");}public virtual void hello4(){Console.WriteLine("hello4 on base instance - virtual on base");Console.WriteLine("func is new and virtual on deriv");}public virtual void hello5(){Console.WriteLine("hello5 on base instance - virtual on base");Console.WriteLine("func is override on deriv");}public void hello6(){Console.WriteLine("hello6 on base instance - NOT virtual on base");Console.WriteLine("func is override on deriv");}}public class derived : based {public void hello(){Console.WriteLine("hello on deriv - non virtual on deriv");Console.WriteLine("func is non virtual on base");}public virtual void hello2(){Console.WriteLine("hello2 on deriv - virtual on deriv");Console.WriteLine("func is virtual on base");}public new virtual void hello3(){Console.WriteLine("hello3 on deriv - new and virtual on deriv");Console.WriteLine("func is non virtual on base");}public new virtual void hello4(){Console.WriteLine("hello4 on deriv - new and virtual on deriv");Console.WriteLine("func is virtual on base");}public override void hello5(){Console.WriteLine("hello5 on deriv - override on deriv");Console.WriteLine("func is virtual on base");}}class Program{static void Main(string[] args){Console.WriteLine("base ref with base inst");based b = new based();b.hello();b.hello2();b.hello3();b.hello4();b.hello5();Console.WriteLine();Console.WriteLine("deriv ref with deriv inst");derived d = new derived();d.hello();d.hello2();d.hello3();d.hello4();d.hello5();Console.WriteLine();Console.WriteLine("base ref with deriv inst");based o = new derived();o.hello();o.hello2();o.hello3();o.hello4();o.hello5();Console.WriteLine();Console.WriteLine("deriv ref with deriv inst cast back to base ref");derived s = new derived();based ds = s;ds.hello();ds.hello2();ds.hello3();ds.hello4();ds.hello5();Console.WriteLine("The end--");Console.ReadLine();}} }
And the output:

base ref with base inst hello on base instance - non virtual on base func is - non virtual on deriv hello2 on base instance - virtual on base func is - virtual on deriv hello3 on base instance - non virtual on base func is new and virtual on deriv hello4 on base instance - virtual on base func is new and virtual on deriv hello5 on base instance - virtual on base func is override on derivderiv ref with deriv inst hello on deriv - non virtual on deriv func is non virtual on base hello2 on deriv - virtual on deriv func is virtual on base hello3 on deriv - new and virtual on deriv func is non virtual on base hello4 on deriv - new and virtual on deriv func is virtual on base hello5 on deriv - override on deriv func is virtual on basebase ref with deriv inst hello on base instance - non virtual on base func is - non virtual on deriv hello2 on base instance - virtual on base func is - virtual on deriv hello3 on base instance - non virtual on base func is new and virtual on deriv hello4 on base instance - virtual on base func is new and virtual on deriv hello5 on deriv - override on deriv func is virtual on basederiv ref with deriv inst cast back to base ref hello on base instance - non virtual on base func is - non virtual on deriv hello2 on base instance - virtual on base func is - virtual on deriv hello3 on base instance - non virtual on base func is new and virtual on deriv hello4 on base instance - virtual on base func is new and virtual on deriv hello5 on deriv - override on deriv func is virtual on base The end--


And lastly Java

package com.roboticsfordreamers;class Base implements {public void Hello(){System.out.println("Hello this the base");} }class Derived extends Base {public void Hello(){System.out.println("Hello this the derived");} }public class Main {public static void main(String[] args) {Base b = new Base();Derived d = new Derived();Base b2 = new Derived();b.Hello();d.Hello();b2.Hello();} } And the output:
Hello this the base Hello this the derived Hello this the derivedProcess finished with exit code 0

我希望你能找到對你有用知識。


原文:https://www.codeproject.com/Tips/1164135/Overriding-Virtual-Functions-a-Comparison-Between

PS:這篇有點(diǎn)難,部分地方翻譯不到位

總結(jié)

以上是生活随笔為你收集整理的让我们来比较C#,C++和Java之间重写虚函数的区别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。