OOP C const成員函式

2021-09-07 11:15:49 字數 3224 閱讀 9043

1、**轉換分析技巧

在早期某些編譯器會將c++**翻譯為c**,然後使用c編譯器生成可執行檔案。其中翻譯的乙個轉化就是:將this指標顯式新增到成員函式的第乙個引數位置上,並在成員函式呼叫時,自動將物件的位址傳遞給引數this。

這個過程用如下**解釋:

#include#include

using

namespace

std;

class

dog

void bark() const

void

feed(unsigned add)

private

: unsigned energe;

};int

main()

翻譯轉換

//

原型轉換為c**後的樣子

void bark(const dog*this

);void feed(dog*this

,unsigned add);

//呼叫時的轉換

dog.feed(2); -----> feed(&dog , 2

); dog.bark(); -----> bark(&dog);

現在的c++編譯器可能不是這樣的工作的,但是,如果你使用這個轉換方式去應用到實際的程式設計的**分析中,很多**和語法特性就會迎刃而解。

2、頂層const,底層const

頂層const:指標變數本身是常量。(頂層const不適合引用,因為引用天生就是乙個常量,始終引用乙個物件,直到消亡)

如   int* const p = &a;

底層const:變數指向(或者引用)的物件被視為常量。(注意這裡的用詞:被視為,因為物件不一定就是常量,也可能是底層const指標、引用的一廂情願)

如    const int*p ;    int const *p;    這二者寫法等價

const int& r;

乙個非底層const指標,它對它指向的物件有 讀、寫的權利,因此,為了確保資料安全,它僅能指向非常量物件。

int a=1

;const

int b = 2

;int*p1 = &a; //

okp1 = &b; //

error不允許

乙個底層const指標,他對它指向的物件僅有讀的權利。因此,它可以指向常量和非常量。

int a=1

;const

int b = 2

;const

int*p1 = &a; //

okp1 = &b ; //

ok

3、函式的引數是否為 底層const 可以作為過載的依據

舉例說,下面2個函式可以過載。

void foo(const

int*p); //a

void foo(int*p); //b

編譯器在過載解析時,根據傳遞的引數來判斷呼叫哪乙個版本。

當僅存在版本a時,若傳遞的是非常量int的指標,或常量int的指標,都可以成功呼叫。

當僅存在版本b時,若傳遞的是非常量int的指標,可以成功呼叫,但不允許傳遞常量int的指標。

當a、b 都存在,過載時,若傳遞的是非常量int的指標,則優先使用版本b,因為這是最匹配的。

若傳遞的是常量int的指標, 則使用版本a。

另外,引數本身是否是const 不作為過載的依據,下面的不能過載。

void foo(const

inta);

void foo(int

a);//

c語言中,引數修飾為const和不使用const修飾 被編譯器一樣對待,c++為相容c,也使用了這個策略。因此二者等價。

在上面的dog類**中,如果去掉bark函式後的const修飾符,並試著用乙個const 物件去呼叫bark函式,則發現編譯器報錯。

void

bark()

/////

const

dog dog;

dog.bark();

//錯誤提示為型別不相容

拋開**,從業務邏輯上來看,bark函式只是在螢幕上輸出訊息,根本不會改變物件的狀態,那即便是const 物件,也必須能成功呼叫啊。

按照最開始介紹的分析方法,發生錯誤的**等價與下面的c**。

const

dog dog;

bark(&dog) //而bark函式轉化後的

原型為:void bark(dog*this);

顯然,將常量的指標賦值給非常量指標是不允許的。

再比如,c++標準庫中的string類,它的用於獲取字串長度的成員函式都是const修飾的。如果不是這樣的話,那麼字串常量就不能獲取他們的長度了,這簡直荒謬!

size_type size() const;

size_type length() const;

成員函式同時存在 const版本和非const版本?可以過載?是的。

同樣,先按照最開始介紹的第1條分析方法,轉換為c**。然後根據第3條的分析就可以了。這裡不再贅述。

最常用的就是,按照約定當過載索引運算子 [ ] 時,會同時編寫乙個 const版本和非const版本。

例如std::vector的[ ]運算子函式

reference       operator

( size_type pos );

const_reference

operator( size_type pos ) const;

1、如果乙個成員函式在邏輯上不會修改物件的狀態(字段),就應該定義為const函式

2、如果物件是const,則它只能呼叫const成員函式。

如果物件是普通的非const物件:

呼叫的某個成員函式是非const函式,則理所當然呼叫它。

呼叫的某個成員函式是const函式,則當然也可以呼叫他。(底層const指標可以指向非常量物件)

呼叫的某個成員函式同時存在 const版本和非const版本,則優先呼叫非const成員函式,編譯器總是使用最匹配的版本。

靜態成員 靜態成員函式

reference to non static member function must be called sort numbers.begin numbers.end cmp 做演算法題的時候遇到的乙個問題,和成員函式相關,這裡記錄一下備忘。首先上 class solution string p...

靜態成員和成員函式

靜態成員在類的所有物件中是共享的。如果不存在其他的初始化語句,在建立第乙個物件時,所有的靜態資料都會被初始化為零。我們不能把靜態成員的初始化放置在類的定義中,但是可以在類的外部通過使用範圍解析運算子 來重新宣告靜態變數從而對它進行初始化 靜態成員函式 如果把函式成員宣告為靜態的,就可以把函式與類的任...

成員函式 非成員函式和友元函式

成員函式和非成員函式最大的區別在於成員函式可以是虛擬的而非成員函式不行。所以,如果有個函式必須進行動態繫結,就要採用虛函式,而虛函式必定是某個類的成員函式。如果函式不必是虛擬的,情況就稍微複雜一點。看下面表示有理數的乙個類 class rational 這是乙個沒有一點用處的類 介面最小,但遠不夠完...