什麼時候該使用前置宣告?

2021-09-27 05:45:23 字數 2292 閱讀 2334

首先,我們為什麼要包括標頭檔案?問題的回答很簡單,通常是我們需要獲得某個型別的定義(definition)。那麼接下來的問題就是,在什麼情 況下我們才需要型別的定義,在什麼情況下我們只需要宣告就足夠了?問題的回答是當我們需要知道這個型別的大小或者需要知道它的函式簽名的時候,我們就需要獲得它的定義。

假設我們有型別a和型別c,在哪些情況下在a需要c的定義:

a繼承至c

a有乙個型別為c的成員變數

a有乙個型別為c的指標的成員變數

a有乙個型別為c的引用的成員變數

a有乙個型別為std::list的成員變數

a有乙個函式,它的簽名中引數和返回值都是型別c

a有乙個函式,它的簽名中引數和返回值都是型別c,它呼叫了c的某個函式,**在標頭檔案中

a有乙個函式,它的簽名中引數和返回值都是型別c(包括型別c本身,c的引用型別和c的指標型別),並且它會呼叫另外乙個使用c的函式,**直接寫在a的標頭檔案中

c和a在同乙個名字空間裡面

c和a在不同的名字空間裡面

1,沒有任何辦法,必須要獲得c的定義,因為我們必須要知道c的成員變數,成員函式。

2,需要c的定義,因為我們要知道c的大小來確定a的大小,但是可以使用pimpl慣用法來改善這一點,詳情請看hurb的exceptional c++。

3,4,不需要,前置宣告就可以了,其實3和4是一樣的,引用在物理上也是乙個指標,它的大小根據平台不同,可能是32位也可能是64位,反正我們不需要知道c的定義就可以確定這個成員變數的大小。

5,不需要,有可能老式的編譯器需要。標準庫裡面的容器像list, vector,map,在包括乙個list,vector,map型別的成員變數的時候,都不需要c的定義。因為它們內部其實也是使用c的指標作為成員變數,它們的大小一開始就是固定的了,不會根據模版引數的不同而改變。

6,不需要,只要我們沒有使用到c。

7,需要,我們需要知道呼叫函式的簽名。

8,8的情況比較複雜,直接看**會比較清楚一些。

c& dotoc(c&);

c& dotoc2(c& c) ;

從上面的**來看,a的乙個成員函式dotoc2呼叫了另外乙個成員函式dotoc,但是無論是dotoc2,還是dotoc,它們的的引數和返 回型別其實都是c的引用(換成指標,情況也一樣),引用的賦值跟指標的賦值都是一樣,無非就是×××的賦值,所以這裡即不需要知道c的大小也沒有呼叫c的任 何函式,實際上這裡並不需要c的定義。

但是,我們隨便把其中乙個c&換成c,比如像下面的幾種示例:

1.c& dotoc(c&);

c& dotoc2(c c) ;          

2.c& dotoc(c);

c& dotoc2(c& c) ;

3.c dotoc(c&);

c& dotoc2(c& c) ;

4.c& dotoc(c&);

c dotoc2(c& c) ;

無論哪一種,其實都隱式包含了乙個拷貝建構函式的呼叫,比如1中引數c由拷貝建構函式生成,3中dotoc的返回值是乙個由拷貝建構函式生成的匿名物件。因為我們呼叫了c的拷貝建構函式,所以以上無論那種情形都需要知道c的定義。

9和10都一樣,我們都不需要知道c的定義,只是10的情況下,前置宣告的語法會稍微複雜一些。

最後給出乙個完整的例子,我們可以看到在兩個不同名字空間的型別a和c,a是如何使用前置宣告來取代直接包括c的標頭檔案的:

a.h#pragma once

#include

#include

#include

#include

//不同名字空間的前置宣告方式

namespace test1

class c;

namespace test2

//用using避免使用完全限定名

using test1::c;

class a 

public:

c  usec(c);

c& dotoc(c&);

c& dotoc2(c& c) ;

private:

std::list_list;

std::vector_vector;

std::map_map;

c*              _pc;

c&              _rc;

c.h#ifndef c_h

#define c_h

#include

namespace test1

class c

public:

void print() {std::cout<<"class c"<

#endif // c_h

什麼時候該休息

睡眠是身體進行自我調整的時刻,你侵略它的時間,它便侵略你的健康 有些人原本一向身體健康,但在連續熬夜數晚後,突然第二天起床會覺得很疲勞,一閉眼就想睡覺,而且會腰痠背痛,但一到晚上精神又好起來!別以為這是小事!根據中醫的看法,是因過勞而造成體內器官陰陽失調,就是體內器官起內訌,互相打架,最後造成器官衰...

到底什麼時候該使用MQ?

mq是幹嘛的 訊息匯流排 message queue 後文稱mq,是一種跨程序的通訊機制,用於上下游傳遞訊息。在網際網路架構中,mq是一種非常常見的上下游 邏輯解耦 物理解耦 的訊息通訊服務。使用了mq之後,訊息傳送上游只需要依賴mq,邏輯上和物理上都不用依賴其他服務。什麼時候不使用訊息匯流排 mq...

到底什麼時候該使用MQ?

一 緣起 一切脫離業務的架構設計與新技術引入都是耍流氓。引入乙個技術之前,首先應該解答的問題是,這個技術解決什麼問題。就像微服務分層架構之前,應該首先回答,為什麼要引入微服務,微服務究竟解決什麼問題 詳見 網際網路架構為什麼要做微服務?不少詢問,究竟什麼時候使用mq,mq究竟適合什麼場景,故有了此文...