欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java、C++中子類對(duì)父類函數(shù)覆蓋的可訪問(wèn)性縮小的區(qū)別介紹

 更新時(shí)間:2018年01月08日 08:44:34   作者:DevBean  
這篇文章主要給大家介紹了關(guān)于Java、C++中子類對(duì)父類函數(shù)覆蓋的可訪問(wèn)性縮小的區(qū)別的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。

前言

“Java 和 C++ 中子類對(duì)父類函數(shù)覆蓋的可訪問(wèn)性縮小的問(wèn)題”的題目看起來(lái)比較學(xué)術(shù)化,但的確是一個(gè)容易忽視的問(wèn)題。本文力求詳細(xì)闡述這一問(wèn)題在 Java 以及 C++ 中的區(qū)別。

先介紹什么是“子類對(duì)父類函數(shù)覆蓋的可訪問(wèn)性縮小”。對(duì)于繼承而言,子類可以覆蓋父類的“虛函數(shù)”——盡管 Java 中沒(méi)有虛函數(shù)這一術(shù)語(yǔ),但可以把 Java 的所有函數(shù)都看作虛函數(shù),因?yàn)?Java 的所有函數(shù)都可以被子類覆蓋。這里僅借用“虛函數(shù)”這一名詞的含義,不深究語(yǔ)言的細(xì)節(jié)。Java 和 C++ 都允許在覆蓋時(shí),改變函數(shù)的可訪問(wèn)性。所謂“可訪問(wèn)性”,就是使用 public 、 protected 、 private 等訪問(wèn)控制符進(jìn)行修飾,用來(lái)控制函數(shù)能否被訪問(wèn)到。通常可訪問(wèn)性的順序?yàn)椋ㄓ捎?C++ 中沒(méi)有包的概念,因此暫不考慮包訪問(wèn)控制符,這并不影響這里的討論):

public > protected > private

以 Java 為例:

class Base {
 protected void sayHello() {
  System.out.println("Hello in Base");
 }
}
class Child extends Base {
 public void sayHello() {
  System.out.println("Hello in Child");
 }
}

注意:這里的 sayHello() 函數(shù)。父類 Base 中,該函數(shù)使用 protected 訪問(wèn)控制符進(jìn)行修飾。而子類將其改用 public ,這不會(huì)有任何問(wèn)題。 子類對(duì)父類函數(shù)覆蓋時(shí),擴(kuò)大可訪問(wèn)性,通常都不是問(wèn)題。

當(dāng)子類對(duì)父類函數(shù)覆蓋的可訪問(wèn)性縮小時(shí),Java 和 C++ 采取了不同的策略。

首先以 Java 為例,看下面的代碼:

class Base {
 public void sayHello() {
  System.out.println("Hello in Base");
 }
}
class Child extends Base {
 private void sayHello() {
  System.out.println("Hello in Child");
 }
}

上面的代碼中,高亮的第 8 行會(huì)有編譯錯(cuò)誤——這段代碼根本不能通過(guò)編譯! Java 不允許子類在覆蓋父類函數(shù)時(shí),縮小可訪問(wèn)性。 至于原因,我們可以用一個(gè)例子來(lái)說(shuō)明。例如我們?cè)陬愅獠繉?xiě)下面的代碼:

Base base = new Base();
base.sayHello();
base = new Child();
base.sayHello();

假如之前的代碼可以通過(guò)編譯,那么就存在這么一種可能:當(dāng) base 指向 new Base() 時(shí), sayHello() 是可以訪問(wèn)到的,但是當(dāng) base 指向 new Child() 時(shí), sayHello() 卻無(wú)法訪問(wèn)到!在 Java 看來(lái)這是一個(gè)矛盾,應(yīng)該避免出現(xiàn)這種問(wèn)題,因此,Java 從編譯器的角度規(guī)定我們不能寫(xiě)出上面的代碼。

針對(duì) C++,情況又有所區(qū)別。來(lái)看 C++ 的例子:

class Base {
public:
  virtual void sayHello() {
    std::cout << "Hello in Base";
  }
}
class Child : public Base {
private:
  void sayHello() {
    std::cout << "Hello in Child";
  }
}

這段代碼在 C++ 中是完全正確的。注意,這里的子類在覆蓋父類函數(shù)時(shí), 縮小 了可訪問(wèn)性。如果你沒(méi)有看出有什么問(wèn)題,那么我們完全可以在類外部寫(xiě)出下面的代碼:

Child child;
child.sayHello(); // 不能通過(guò)編譯,因?yàn)?sayHello() 是 private 的
static_cast<Base&>(child).sayHello(); // 可以通過(guò)編譯,因?yàn)?sayHello() 是 public 的

第 2 行調(diào)用是失敗的,因?yàn)樵?Child 中, sayHello() 是 private 的,不能在外部調(diào)用。然而,當(dāng)我們使用 static_cast 將 Child 強(qiáng)制轉(zhuǎn)換成 Base 對(duì)象時(shí),事情發(fā)生了改變——對(duì)于 Base 而言, sayHello() 是 public 的,因此可以正常調(diào)用。

針對(duì)這一點(diǎn),C++ 標(biāo)準(zhǔn)的 Member access control 一章中的 Access to virtual functions 一節(jié)可以找到如下的例子:

class B {
public:
  virtual int f();
};
class D : public B {
private:
  int f();
};
void f() {
  D d;
  B* pb = &d;
  D* pd = &d;
  pb->f(); // OK: B::f() is public, D::f() is invoked
  pd->f(); // error: D::f() is private
}

對(duì)此,C++ 標(biāo)準(zhǔn)給出的解釋是:

 Access is checked at the call point using the type of the expression used to denote the object for which the member function is called ( B* in the example above). The access of the member function in the class in which it was defined (D in the example above) is in general not known.

簡(jiǎn)單翻譯過(guò)來(lái)有兩條要點(diǎn):

  • 訪問(wèn)控制是在調(diào)用時(shí)檢查的,也就是說(shuō),誰(shuí)調(diào)用了這個(gè)函數(shù),就檢查誰(shuí)能不能訪問(wèn)這個(gè)函數(shù)
  • 類中成員函數(shù)的可訪問(wèn)性一般而言是不知道的,也就是說(shuō),檢查可訪問(wèn)性時(shí),并不能知道這個(gè)函數(shù)在定義時(shí)到底是 public 的還是 private 的,因此也就無(wú)法據(jù)此檢查可訪問(wèn)性

正因如此,C++ 的調(diào)用方似乎可以通過(guò)一些技巧性轉(zhuǎn)換,“巧妙地”調(diào)用到原本無(wú)法訪問(wèn)的函數(shù)。一個(gè)更加實(shí)際的例子是:Qt 里面, QObject::event() 函數(shù)是 public ,而其子類 QWidget 的 event() 函數(shù)則改變成 protected 。具體可以閱讀 Qt 的相關(guān)代碼。

總結(jié)來(lái)說(shuō),在子類覆蓋父類函數(shù)時(shí),Java 嚴(yán)格限制了子類不能縮小函數(shù)可訪問(wèn)性,但 C++ 無(wú)此限制。個(gè)人認(rèn)為,從軟件工程的角度來(lái)說(shuō),Java 的規(guī)定無(wú)疑更具有工程上面的意義,函數(shù)的調(diào)用也更加一致。C++ 的標(biāo)準(zhǔn)則會(huì)明顯簡(jiǎn)化編譯器實(shí)現(xiàn),但是對(duì)工程而言并不算很好的參考。

PS:C++ 標(biāo)準(zhǔn)的正式版是需要購(gòu)買(mǎi)的,但是草案可以免費(fèi)下載。C++ 標(biāo)準(zhǔn)草案的下載地址可以在下面的頁(yè)面找到: https://isocpp.org/std/the-standard

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • Java責(zé)任鏈模式模板代碼分享

    Java責(zé)任鏈模式模板代碼分享

    這篇文章主要介紹了Java責(zé)任鏈模式模板代碼分享,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01
  • mybatis Interceptor對(duì)UpdateTime自動(dòng)處理的實(shí)現(xiàn)方法

    mybatis Interceptor對(duì)UpdateTime自動(dòng)處理的實(shí)現(xiàn)方法

    這篇文章主要給大家介紹了關(guān)于使用mybatis Interceptor對(duì)UpdateTime自動(dòng)處理的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧
    2018-12-12
  • Spring中的@ConditionalOnProperty注解使用詳解

    Spring中的@ConditionalOnProperty注解使用詳解

    這篇文章主要介紹了Spring中的@ConditionalOnProperty注解使用詳解,在 spring boot 中有時(shí)候需要控制配置類是否生效,可以使用 @ConditionalOnProperty 注解來(lái)控制 @Configuration 是否生效,需要的朋友可以參考下
    2024-01-01
  • spring aop兩種配置方式

    spring aop兩種配置方式

    這篇文章主要為大家詳細(xì)介紹了spring aop兩種配置方式,主要是注解配置AOP和xml配置aop,需要的朋友可以參考下
    2015-09-09
  • 使用java采集京東商城區(qū)劃數(shù)據(jù)示例

    使用java采集京東商城區(qū)劃數(shù)據(jù)示例

    這篇文章主要介紹了java采集京東的全國(guó)區(qū)劃數(shù)據(jù)示例,保存成json形式,如想轉(zhuǎn)換到數(shù)據(jù)庫(kù)只需反序列化為對(duì)象保存到數(shù)據(jù)庫(kù)即可
    2014-03-03
  • Idea中指定xml文件失效的解決過(guò)程

    Idea中指定xml文件失效的解決過(guò)程

    最近在開(kāi)發(fā)的過(guò)程中遇到了一個(gè)奇怪的問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于Idea中指定xml文件失效的解決過(guò)程,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • JavaWeb讀取配置文件的四種方法

    JavaWeb讀取配置文件的四種方法

    這篇文章主要介紹了JavaWeb讀取配置文件的4種方法,方法一采用ServletContext讀取,方法二采用ResourceBundle類讀取配置信息,方法三采用ClassLoader方式進(jìn)行讀取配置信息,對(duì)javaweb讀取配置文件的四種方法感興趣的朋友參考下吧
    2018-03-03
  • 關(guān)于weblogic部署Java項(xiàng)目的包沖突問(wèn)題的解決

    關(guān)于weblogic部署Java項(xiàng)目的包沖突問(wèn)題的解決

    這篇文章主要介紹了關(guān)于weblogic部署Java項(xiàng)目的包沖突問(wèn)題的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-01-01
  • SpringBoot實(shí)現(xiàn)各種參數(shù)校驗(yàn)總結(jié)(建議收藏!)

    SpringBoot實(shí)現(xiàn)各種參數(shù)校驗(yàn)總結(jié)(建議收藏!)

    本文深入解析了Spring?Validation的使用方法、實(shí)現(xiàn)原理及最佳實(shí)踐,詳細(xì)介紹了各種參數(shù)校驗(yàn)場(chǎng)景,如requestBody和requestParam/PathVariable的使用,并探討了分組校驗(yàn)、嵌套校驗(yàn)和自定義校驗(yàn)的高級(jí)應(yīng)用,需要的朋友可以參考下
    2024-09-09
  • SpringMVC中Model和ModelAndView的EL表達(dá)式取值方法

    SpringMVC中Model和ModelAndView的EL表達(dá)式取值方法

    下面小編就為大家分享一篇SpringMVC中Model和ModelAndView的EL表達(dá)式取值方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03

最新評(píng)論