最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

前言

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

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

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 訪問控制符進行修飾。而子類將其改用 public ,這不會有任何問題。 子類對父類函數(shù)覆蓋時,擴大可訪問性,通常都不是問題。

當子類對父類函數(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 行會有編譯錯誤——這段代碼根本不能通過編譯! Java 不允許子類在覆蓋父類函數(shù)時,縮小可訪問性。 至于原因,我們可以用一個例子來說明。例如我們在類外部寫下面的代碼:

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

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

針對 C++,情況又有所區(qū)別。來看 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ù)時, 縮小 了可訪問性。如果你沒有看出有什么問題,那么我們完全可以在類外部寫出下面的代碼:

Child child;
child.sayHello(); // 不能通過編譯,因為 sayHello() 是 private 的
static_cast<Base&>(child).sayHello(); // 可以通過編譯,因為 sayHello() 是 public 的

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

針對這一點,C++ 標準的 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
}

對此,C++ 標準給出的解釋是:

 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.

簡單翻譯過來有兩條要點:

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

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

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

PS:C++ 標準的正式版是需要購買的,但是草案可以免費下載。C++ 標準草案的下載地址可以在下面的頁面找到: https://isocpp.org/std/the-standard

總結(jié)

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

相關(guān)文章

  • 用java將GBK工程轉(zhuǎn)為uft8的方法實例

    用java將GBK工程轉(zhuǎn)為uft8的方法實例

    本篇文章主要介紹了用java將GBK工程轉(zhuǎn)為uft8的方法實例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • 詳解分別用Kotlin和java寫RecyclerView的示例

    詳解分別用Kotlin和java寫RecyclerView的示例

    本篇文章主要介紹了詳解分別用Kotlin和java寫RecyclerView的示例,詳解分別用Kotlin和java寫RecyclerView的示例
    2017-12-12
  • Java項目中防止SQL注入的四種方案總結(jié)

    Java項目中防止SQL注入的四種方案總結(jié)

    SQL注入是一種代碼注入技術(shù),通過把SQL命令插入到Web表單遞交或輸入域名或頁面請求的查詢字符串,最終達到欺騙服務(wù)器執(zhí)行惡意的SQL命令,下面我們就來看看如何在項目中防止SQL注入吧
    2023-10-10
  • Java防止非法盜鏈的幾種解決方案

    Java防止非法盜鏈的幾種解決方案

    防止別人通過一些技術(shù)手段盜用本站的資源,本文主要介紹了Java防止非法盜鏈的幾種解決方案,具有一定的參考價值,感興趣的可以了解一下
    2023-10-10
  • Spring Cloud之服務(wù)監(jiān)控turbine的示例

    Spring Cloud之服務(wù)監(jiān)控turbine的示例

    這篇文章主要介紹了Spring Cloud之服務(wù)監(jiān)控turbine的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05
  • Java關(guān)于含有繼承類的成員初始化過程講解

    Java關(guān)于含有繼承類的成員初始化過程講解

    今天小編就為大家分享一篇Java關(guān)于含有繼承類的成員初始化過程講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • Java數(shù)組的運用詳解

    Java數(shù)組的運用詳解

    這篇文章主要給大家介紹了關(guān)于Java中數(shù)組的定義和使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-08-08
  • SpringBoot?Validation快速實現(xiàn)數(shù)據(jù)校驗的示例代碼

    SpringBoot?Validation快速實現(xiàn)數(shù)據(jù)校驗的示例代碼

    在實際開發(fā)中,肯定會經(jīng)常遇到對參數(shù)字段進行校驗的場景,通常我們只能寫大量的if else來完成校驗工作,而如果使用SpringBoot Validation則可以輕松的通過注解來完成,接下來小編給大家介紹下利用SpringBoot?Validation快速實現(xiàn)數(shù)據(jù)校驗的示例代碼,需要的朋友參考下吧
    2022-06-06
  • Spring?Cloud?Gateway服務(wù)網(wǎng)關(guān)限流問題及解決

    Spring?Cloud?Gateway服務(wù)網(wǎng)關(guān)限流問題及解決

    這篇文章主要介紹了Spring?Cloud?Gateway服務(wù)網(wǎng)關(guān)限流問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • JAVA中 終止線程的方法介紹

    JAVA中 終止線程的方法介紹

    JAVA中 終止線程的方法介紹,需要的朋友可以參考一下
    2013-03-03

最新評論

偏关县| 南涧| 眉山市| 巨鹿县| 吉安市| 卫辉市| 阿荣旗| 丰都县| 称多县| 上蔡县| 五家渠市| 定结县| 颍上县| 高清| 宜阳县| 大化| 高安市| 宜州市| 阜康市| 闸北区| 天门市| 增城市| 灵山县| 酒泉市| 阿拉尔市| 广宗县| 五大连池市| 大连市| 德惠市| 乌鲁木齐市| 新龙县| 潞西市| 翁源县| 兖州市| 淮安市| 景德镇市| 邹平县| 普安县| 凤凰县| 泽普县| 郸城县|