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

詳解C++ 前置聲明

 更新時間:2020年09月09日 11:49:30   作者:tlanyan  
這篇文章主要介紹了C++ 前置聲明的相關(guān)資料,幫助大家更好的理解和使用c++,感興趣的朋友可以了解下

前置聲明是C/C++開發(fā)中比較常用的技巧,主要用在三種情形:

  1. 變量/常量,例如extern int var1;;
  2. 函數(shù),例如void foo();,注意類的成員函數(shù)無法單獨做前置聲明;
  3. 類,例如class Foo;,也可以前置聲明模板類:template class<typename T1, int SIZE>Foo;。如果類包含在名字空間中,需在名字空間內(nèi)做前置聲明:namespace tlanyan {class Foo;};,而不能這樣:class tlanyan::Foo;。

前置聲明作用

根據(jù)其用途,前置聲明的主要作用為:

  1. 避免重復(fù)定義變量;
  2. 避免引入函數(shù)定義/聲明文件,從而函數(shù)文件發(fā)生更改時不會重新編譯依賴文件;
  3. 解決循環(huán)依賴問題。

前兩種用途好理解,第三種稍微復(fù)雜點,但卻是前置聲明最重要的用途。其解決類A包含類B,同時類B包含類A的依賴問題。循環(huán)依賴一般是設(shè)計層面的問題,可通過接口、引入輔助類等手段化解。前置聲明也能解決,只是架構(gòu)上稍微別扭。

不管A和B是否定義在同一個文件中,c++永遠(yuǎn)無法解決如下形式的循環(huán)依賴(后文解釋原因):

// file: A.hpp
#include "B.hpp"
class A {
 int id;
 B b;
};

// file: B.hpp
#include "A.hpp"
class B {
 ...
 A a;
};

前置聲明解決該問題需要與指針配合,轉(zhuǎn)換成另一種形式。要點如下:

  1. 至少將某類的變量類型轉(zhuǎn)換成指針,例如A中將B轉(zhuǎn)成B*;
  2. 類A中對B使用前置聲明;
  3. 類A的定義文件中移除對類B文件的包含(做了包含保護(hù)則可忽略)。

使用前置聲明后,以下是一種可行的解決形式(兩個類均使用了前置聲明):

// file: A.hpp
//3. 移除對B的包含(使用了#pragma once或者#ifndef B_HPP等保護(hù)措施則無必要)

// 2. 前置聲明類B
class B;
class A {
 int id;
 // 1. 成員變量轉(zhuǎn)換成指針
 B* b;
};

// file: B.hpp
// 3. 移除對A的包含(有包含保護(hù)則非必要)

// 2. 前置聲明類A
class B {
 ...
 // 1. 成員變量轉(zhuǎn)換成指針
 A* a;
};

深入前置聲明

如果你有其他編程語言的經(jīng)驗,會發(fā)現(xiàn)c++有點怪異:Java/C#/Python/PHP等語言可以輕松做到循環(huán)引用,無需使用類似的前置聲明技巧。這不禁讓人思考:C++為何必須要用前置聲明才能化解?

原因在于C++定義對象有兩種方式:一種是A a形式,a即對象,調(diào)用成員變量或函數(shù)用.,對象在棧中分配;另一種是A* a,a是指針,調(diào)用成員變量或函數(shù)用->,其指向地址存儲實際對象,對象在堆中分配。

分配對象需要知道具體的內(nèi)存大小,但以下形式我們不能確定類A和類B對象的大?。?/p>

class A {
  B b;
};
class B {
  A a;
};

對于這個簡單例子,你可以直觀認(rèn)為A和B占用同樣的內(nèi)存,例如1字節(jié),但也可以是2字節(jié),3字節(jié)等;根據(jù)內(nèi)存對齊要求,一般是4字節(jié),8字節(jié)等。無論哪種情況,編譯器無法確定其對象占用內(nèi)存,便會報錯停止編譯。所以你應(yīng)該知道為什么C++永遠(yuǎn)不應(yīng)該(不能)這樣做了吧?

那為何前置聲明加指針的組合能解決循環(huán)引用問題的呢?因為正常情況下,數(shù)據(jù)類型指針在同一機(jī)器的編譯器里占同樣的內(nèi)存。指針一般是4或者8個字節(jié),對應(yīng)32和64位指針。用了指針,即使有循環(huán)引用,類的大小也能輕易的確定下來。這也是Java/C#/Python/PHP等可以輕松循環(huán)引用的原因:這些語言中,對象變量其實都是指針,也意味著對象變量都是引用傳遞。

如果不移除文件的相互包含,能否省去前置聲明呢?答案是不能,原因如下:

  1. C++按照一個個編譯單元(translation unit)進(jìn)行編譯,如果兩個文件互相包含且沒有#pragma once等包含保護(hù)措施,則會出現(xiàn)遞歸包含,編譯器報錯;
  2. 如果兩個頭文件都有文件包含保護(hù),編譯A時會把B包含進(jìn)來,但因為B包含了A,A中的包含保護(hù)生效,導(dǎo)致B文件內(nèi)的內(nèi)容實際未引入A,于是報B為未知符號的錯誤。

總的來說,不管是否移除對方的頭文件,前置聲明都是必須的。實踐中為了避免文件變動時重新編譯的耗費,移除不必要的頭文件是一個好習(xí)慣。

以上就是詳解C++ 前置聲明的詳細(xì)內(nèi)容,更多關(guān)于C++ 前置聲明的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++實現(xiàn)轉(zhuǎn)置矩陣的循環(huán)

    C++實現(xiàn)轉(zhuǎn)置矩陣的循環(huán)

    大家好,本篇文章主要講的是C++實現(xiàn)轉(zhuǎn)置矩陣的循環(huán),感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2022-01-01
  • OpenCV實現(xiàn)圖像的直線檢測

    OpenCV實現(xiàn)圖像的直線檢測

    這篇文章主要為大家詳細(xì)介紹了OpenCV實現(xiàn)圖像直線檢測的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • C++利用std::forward_list查找插入數(shù)據(jù)方法示例

    C++利用std::forward_list查找插入數(shù)據(jù)方法示例

    這篇文章主要給大家介紹了關(guān)于C++利用std::forward_list查找插入數(shù)據(jù)的相關(guān)資料,文中先對std::forward_list進(jìn)行了詳細(xì)的介紹,而后通過示例代碼給大家介紹了查找的方法,需要的朋友可以參考借鑒,下面話不多說了,來一起看看吧。
    2017-08-08
  • c++代碼調(diào)試方式的幾點建議

    c++代碼調(diào)試方式的幾點建議

    這篇文章主要介紹了c++代碼調(diào)試方式的幾點建議,幫助大家更好的理解和學(xué)習(xí)c++,感興趣的朋友可以了解下
    2020-08-08
  • C語言超詳細(xì)講解遞歸算法漢諾塔

    C語言超詳細(xì)講解遞歸算法漢諾塔

    漢諾塔問題是一個經(jīng)典的問題。漢諾塔(Hanoi Tower),又稱河內(nèi)塔,源于印度一個古老傳說。本文將用Java求解這一問題,感興趣的可以學(xué)習(xí)一下
    2022-05-05
  • C++11中多線程編程-std::async的深入講解

    C++11中多線程編程-std::async的深入講解

    這篇文章主要給大家介紹了關(guān)于C++11中多線程編程-std::async的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • C++中的pair使用詳解

    C++中的pair使用詳解

    pair是定義在<utility>中的生成特定類型的模板,它的作用是把一組數(shù)據(jù)合并為一體,實際上是一個擁有兩個成員變量的struct,這篇文章主要介紹了c++的pair使用,需要的朋友可以參考下
    2022-09-09
  • C語言實現(xiàn)數(shù)組元素排序方法詳解

    C語言實現(xiàn)數(shù)組元素排序方法詳解

    這篇文章主要為大家介紹了C語言算法練習(xí)中數(shù)組元素排序的實現(xiàn)方法,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)C語言有一定幫助,需要的可以參考一下
    2023-02-02
  • c語言的指針數(shù)組詳解

    c語言的指針數(shù)組詳解

    這篇文章主要為大家介紹了c語言的指針數(shù)組,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • C++ 如何使用RapidJson 寫入文件

    C++ 如何使用RapidJson 寫入文件

    RapidJSON 是只有頭文件的 C++ 庫, 不需要編譯, 可以直接在項目中使用, 只需把 include/rapidjson 目錄復(fù)制至系統(tǒng)或項目的 include 目錄即可,下面給大家分享C++ 如何使用RapidJson 寫入文件,感興趣的朋友跟隨小編一起看看吧
    2024-04-04

最新評論

金华市| 金湖县| 洛隆县| 犍为县| 澄江县| 柏乡县| 榆中县| 深州市| 股票| 桦甸市| 长汀县| 仪征市| 尖扎县| 乃东县| 新宁县| 深圳市| 昔阳县| 林州市| 出国| 广德县| 台东市| 当涂县| 盈江县| 连云港市| 宁晋县| 旌德县| 苍南县| 山阳县| 和林格尔县| 阜宁县| 鱼台县| 桓仁| 扎鲁特旗| 琼结县| 五寨县| 平乡县| 固始县| 阳山县| 新竹县| 和田市| 清涧县|