C 關於類以及h cpp檔案的一些實用知識

2021-09-01 12:25:51 字數 2902 閱讀 3675

解決重定義問題,首先要明白vc的編譯原理:

1. 微軟預編譯控制

#if _msc_ver > 1000

#pragma once

#endif

... ... // .h檔案正文

在.h檔案最開始的地方加上這段**,即可避免標頭檔案重複include。但是需要注意的是#pragma once 這條語句只有vc編譯器大於1000才可以支援(反正vc++6.0及以上是可以的),_msc_ver就是microsoft的c編譯器的版本。

#pragma once則由編譯器提供保證:同乙個檔案不會被包含多次。注意這裡所說的「同乙個檔案」是指物理上的乙個檔案,而不是指內容相同的兩個檔案。帶來的好處是,你不必再費勁想個巨集名了,當然也就不會出現巨集名碰撞引發的奇怪問題。對應的缺點就是如果某個標頭檔案有多份拷貝,本方法不能保證他們不被重複包含。當然,相比巨集名碰撞引發的「找不到宣告」的問題,重複包含更容易被發現並修正。

2、巨集定義方式

#ifndef __somefile_h__

#define __somefile_h__

... ... // .h檔案正文

#endif

#ifndef的方式依賴於巨集名字不能衝突,這不光可以保證同乙個檔案不會被包含多次,也能保證內容完全相同的兩個檔案不會被不小心同時包含。當然,缺點就是如果不同標頭檔案的巨集名不小心「撞車」,可能就會導致標頭檔案明明存在,編譯器卻硬說找不到宣告的狀況 。不過如果是編譯器自動生成的類一般都會自動根據編譯次數(唯一)來自動生成唯一的巨集名。

在專案同時使用第三方庫guilib和cj609lib,編譯提示結構體cmenuiteminfo重定義,後來研究了一下,發現guilib和cj609lib中都全域性定義了同乙個結構體名cmenuiteminfo,而解決方法有兩種:使用巨集定義規避和使用命名空間

1.巨集定義規避

#ifndef __cmenuiteminfo_local_defined//避免結構體cmenuiteminfo重複定義

#define __cmenuiteminfo_local_defined

struct cmenuiteminfo : public menuiteminfo_local

};#endif//__cmenuiteminfo_local_defined

這樣做的好處是,用cmenuiteminfo定義具體物件時,直接使用cmenuiteminfo,程式會自動使用編譯過程遇到的第乙個cmenuiteminfo的定義。

但這種方法有乙個前提:兩個結構體的定義必須一致,也就是說上述關於cmenuiteminfo的兩個定義必須一致,很巧的是guilib和cj609lib關於cmenuiteminfo的定義確實一致。

2.使用命名空間

這種方法更加廣泛,尤其適合於重名且定義的內容不一樣的情況。這種方法等有時間了,我再在下邊補充,本次使用了巨集定義就解決了上述問題。

ps:最後補充一點,有的時候提示@.obj已經在@.obj中定義的時候,在專案屬性配置中啟用預編譯頭可能會解決這個問題,但不知道是什麼原理。

關於程式中使用的全域性變數,最好在cpp檔案中定義,然後在.h中宣告,這樣可以極大的概率避免重複定義

a.cpp檔案定義全域性變數global_time

#include "a.h "

int global_time;

void main

在a.h檔案中宣告全域性變數

externint global_time;
當b.cpp中要使用global_time,直接在b.h檔案中宣告extern int global_time;,就行了。此時即使已經在b.h或b.cpp檔案中已經引入a.h檔案,也不會衝突。

編譯器一般是禁止在宣告和定義同時定義預設引數值。若宣告時沒有定義預設引數值,那麼在定義成員函式時可以定義預設引數值。但這種情況下,使用函式的使用者是看不見的,很可能會帶來災難性的後果。因此為了程式的可讀性,我們最好在h檔案中宣告成員函式的時候定義預設值,而不要在定義函式的時候定義預設值。

建構函式初始化列表以乙個冒號開始,接著是以逗號分隔的資料成員列表,每個資料成員後面跟乙個放在括號中的初始化式。例如:

class cstudent

}

當我們需要例項化物件的時候,直接這樣即可

cstuden student(10,20);
上面的建構函式(使用初始化列表的建構函式)顯式的初始化類的成員。和下面這樣沒使用初始化列表進行顯式的初始化,而是內部賦值是一樣的。

class cstudent

}

初始化和賦值對內建型別的成員沒有什麼大的區別,像上面的任乙個建構函式都可以。但有的時候必須用帶有初始化列表的建構函式:

一定要注意初始化列表的成員初始化順序:c++初始化類成員時,是按照宣告的順序初始化的,而不是按照出現在初始化列表中的順序。

class cstudent

}

例項化的時候

cstudent stude(10,20);
你可能以為上面的**將會首先做b=x,然後做a=b,最後它們有相同的值都是10。但是編譯器先初始化a,然後是b,因為它們是按這樣的順序宣告的。結果是a將有乙個不可**的值。有兩種方法避免它,乙個是總是按照你希望它們被初始化的順序宣告成員,第二個是,如果你決定使用初始化列表,總是按照它們宣告的順序羅列這些成員。這將有助於消除混淆。

關於greater int 以及類模板的一些理解

1.以greater類模板為例 template class t struct greater public binary functionbool 我們可以看到,greater原型如上,則單拿出greater來說,規定其為類模板。如果我們寫greater或者greater或者單精度浮點型之類的基本...

關於C 類的一些想法

每個類在例項化物件的時候,都會呼叫建構函式在記憶體裡面劃出一塊記憶體,這個記憶體裡面的頭4個位元組是給虛函式用的,有n個虛函式就要用4n個位元組。建構函式的目的就是初始化這塊記憶體,對記憶體進行劃分,所以,一般類不要搞太複雜,不然記憶體會很大。同理 開啟每乙個網頁的時候,就是在例項化乙個物件,開啟的...

關於一些常用類

包裝類1 string類 string物件嗲表一組不可改變的unicode字串行 string物件變數實際是乙個倡廉物件 常用方法 length 獲取長度 split 分割字串 charat 獲取指定位置的字元 1 replace char oldchar,char newchar 將當前字串物件中...