C 語法雜談

2021-09-07 03:46:54 字數 3356 閱讀 6491

建構函式、析構函式和虛函式

1. 虛函式機制在建構函式和析構函式中不起作用:在這兩個函式中呼叫虛函式,總是得到虛函式的本地版本;

2. 析構函式自身常常需要設定為虛函式。比如下面的例子。

class

base

{};class derived : public

base

{};base *p = new

derived;

delete p;

上面的例子中,由於p是base類指標,因此類derived的析構函式將不會得到執行。如果類derived中進行了資源分配操作並在析構函式中釋放,那就悲劇了。

運算子過載

我們從operator+談起。比如我們有乙個類a:

a a::operator+(const a& a) const

這是比較經典的成員函式過載定義,接受乙個引用引數,返回物件a。我們可以在返回的臨時物件上做事情:

(a1+a2).do_something();   //

a1和a2都是a物件,do_something是普通成員函式。

但這種寫法稍微違背直覺(見下文:對臨時變數的引用只能是常量引用)。所以建議將operator+的返回值設定為const物件,這樣就可以了。

c++編譯器預設提供的成員函式

建構函式,析構函式,拷貝建構函式,賦值運算子,位址運算子。

如果你的類裡包含指標,小心了。

賦值表示式和側效

以下表示式行為未定義(?)

a funca1()

a funca2()

funca1() = funca2();

funca1和funca2在vs2013和mingw-gcc4.7.1上有不同的執行順序。

因此,對於以下寫法,最好避免:

a a2 = a1;

上面這條語句在不同的編譯環境下可能由於不同的結果:

結果1:使用預設建構函式構造a2,然後通過賦值運算子將a1賦值給a2。

結果2:通過拷貝建構函式從a1構造出a2。

儘管大多數編譯器足夠智慧型,不會跑到結果1,但為了我們的理想國度,可以這樣寫:

a a2(a1);

對臨時變數的引用只能是常量引用

const

int& i = 1

;const a& a =generate_a_instance();

//generate_a_instance()返回乙個class a的例項:

a generate_a_instance

此處必須使用常量引用的原因是強迫編譯器為該臨時變數分配持續儲存空間,非常量引用不具備該能力(模擬下const int& i = 1而不能寫int& i = 1)。但臨時變數本身未必是常量(除非上例中將函式generate_a_instance返回值設定為const a),所以你可以對臨時變數呼叫非常量成員函式。

附註:vs2013允許對generate_a_instance的返回物件進行非常量引用,但這似乎不合邏輯:它不允許對返回內建物件(例如int值)的函式進行非常量引用。

所以建議在盡可能情況下將返回物件的函式設定為const返回,這樣就可以了。 雖然這樣做會造成不能generate_a_instance().do_something(),但這從邏輯上能講得通。

static

當static出現在類內部修飾資料成員,表示的是「所有類物件唯一」,因此在定義時不能再加static修飾:

//

.cpp file

//假設class a有乙個靜態成員int i

//這是乙個定義,因此一般放在cpp檔案內。

//同樣因為這是乙個定義,需要再次說明其型別int

//但不能加上static,

//否則就會變成「這個變數i僅在該cpp內部有效」的意思。

int a::i = 0;

成員指標

對類內的資料物件使用成員指標是合乎語法但沒有必要的(?),普通指標語法即可指向類內資料成員;成員指標的主要用途在成員函式上:因為類的成員函式帶有隱藏引數this,所以沒有辦法用一般的函式指標指向類內成員函式。另一方面,也正是由於這個原因,兩個不同類中具有相同引數和返回值的函式是不能用同乙個指標去指向的。除此以外,成員指標的定義、賦值、呼叫和普通函式指標是一樣的。

class

a

void func2()

};int _tmain(int argc, _tchar*argv)

成員指標必須和物件繫結,因此即使在類內部定義使用,也必須用this->* 。

const

const表示「一旦定義就不能被改變的量」,除了可代替#define作為編譯期常量之外,還可用於如下環境:

const int i = cin.get();

以上,i不是編譯期常量,每次執行都可能不一樣;但它在定義之後不能改變。

handle class

儘管c++通過private關鍵字實現了私有部分在語法上的分離,但修改乙個類的private部分仍然可能造成所有使用該類的檔案重新編譯(比如增加乙個private函式)。我們可以僅將公共介面部分放置於標頭檔案中,所有私有部分另起乙個class或struct放置在實現檔案中,在標頭檔案中通過乙個指標(handle)指向該私有class。

//

引自c++程式設計思想,1st edition

//介面(.h)檔案

class

handle;//

實現(.cpp)檔案

//巢狀結構使用範圍分解運算子定義

//class handle的私有部分放在這裡

struct

handle::cheshire

;void

handle::initialize()

友元類宣告友元類可以看做一種前向宣告,所以宣告友元類時不需要具體的類定義。

另一方面,如果將類的成員函式作為友元,那麼類定義是需要的。

classc;

class

a;

虛函式1. 如果你在基類中將某個函式宣告為純虛函式,那麼該類是不可例項化的;你必須在它的某個子類中給出該虛函式的實際定義。

2. 如果你在基類中將某個函式宣告為非純的虛函式,那麼必須提供該函式的定義,否則編譯器會報錯,因為無法在沒有函式定義的情況下構造虛函式表;

綜上,虛函式的用法必居其下之一:

1. 在基類中將某個函式宣告為純虛函式,該類不可例項化,在子類中有該函式定義;

2. 在基類中將某個函式宣告為非純的虛函式,且提供該函式定義。

以下是非虛的函式可以做到而虛函式不行的:

在類中僅宣告而不定義某個函式,只要你沒有呼叫該函式。

C 雜談 C 指標

1.何為指標 程式執行時,任何變數都是存放在記憶體中的,通過將記憶體以位元組的大小劃分,為每個位元組增添索引,某一變數的位址就是該變數在記憶體中所佔的第乙個位元組的索引。此時,定義一變數用來存放開始第乙個位元組的索引,這個變數就被稱為指標,通過該變數的值可以間接的訪問該指標所指向的變數。在32位系統...

c 技術雜談

while scanf d n 這個while迴圈裡面的語句代表當輸入為空或者讀取到最後乙個值時停止迴圈,代表按位取反 const和指標的三種經典組合 const int p 指向常量的指標 char const p a 常指標 const char const p a 指向常量的常指標 左移 右移...

c 模板雜談

實驗環境 linux mint 下 qt 5.11 說白了,模板就是搭個函式,類的框架,具體實現的時候往裡面填充內容,或者我們可以把型別名想作乙個佔位符號 include include using namespace std template type returnmax type x,type ...