C 箴言之用屬性來訪問類的私有成員

2022-08-28 03:30:15 字數 2878 閱讀 7527

在程式中,難免要訪問某個物件的私有成員。那麼以前實現這類功能的方法有兩種,第一種方法最簡單,就是把成員訪問符從「private」改為「public」即可;而另乙個就是提供公有的成員訪問函式來進行訪問。那麼現在用c#編寫程式,就不再需要採用前面所說的兩種方法了,而直接使用屬性來完成。

首先來看看三種方法的如何實現以及呼叫的,這裡用乙個例子來說明,即訪問「employeeinfo」類的私有成員strname,具體如下**所示。

那麼這三種方法有什麼區別呢,用如下的**,可以更好的說明三者的區別。

因此可以看出使用屬性不但沒有破壞類的封裝性,沒有減弱**的安全性,而且和第一種方法一樣簡便,只是在效率方面要略低於第一種方法。但總體看來,在c#中用屬性來訪問類的私有成員是不二的選擇。

不過對於使用屬性,以及如上**所說的,難免會有人產生如下一些疑問。

疑問一:就是用屬性是否能達到成員函式那樣的效果,即完成複雜的**操作。

其實屬性的底層實現是借助於成員函式,只不過這部分轉換是由系統幫忙做的,所以在編寫屬性的時候,可以像編寫成員函式一樣,即在成員函式中所能寫的**片斷,完全可以在屬性中套用。下面就貼出屬性所轉換的微軟中間語言(msil)**。

.property instance string name()

// end of property employeeinfo::name

.method public hidebysig specialname instance string get_name() cil managed

// end of method employeeinfo::get_name

.method public hidebysig specialname instance void set_name(string 'value') cil managed

// end of method employeeinfo::set_name

如上就是前面employeeinfo類的name屬性所轉換的中間語言**(不過省略了函式的具體實現**,因為這裡並不是為了研究中間語言**,如果需要對這部分有更多地了解,參看中間語言相關書籍)。

疑問二:就是用屬性的效率是否僅次於第一種方法。

從上面很容易看出,屬性在編譯的時候會轉換成和成員函式一樣的**,那麼它的效率應該和成員函式是一樣的。其實並不是這樣,因為jit編譯器會把屬性所轉換成的兩個成員函式作為內聯函式,這樣效率會提高很多。(注:內聯函式是**被插入到呼叫者**處的函式,通過避免函式呼叫所產生的額外開銷,從而提高執行效率。不過書中也提到,即使不是內聯函式,成員函式相對於方法一的效率損失也是微乎其微的。)

用c#寫程式,一提到屬性,大家都會編寫。其實在屬性中,可以產生很多應用,接著來就分別說明。

<!--[if !supportlists]-->1. <!--[endif]-->在屬性中使用索引符,例如像「arraylist[i]」來訪問arraylist某個成員。這裡需要注意的是,屬性名以及索引引數的編碼格式是固定的,如「this […]」。不過索引引數可以是多個,而且不光支援整型引數,還可以使用其他型別引數。例如:

public returnvaluetype this[ partype1 parvalue1, partype2 parvalue2]

set} 

<!--[if !supportlists]-->2. <!--[endif]-->可以給屬性操作加上互斥鎖,以防止多執行緒操作時而產生的併發錯誤,具體如下。

public string name

}set}}

<!--[if !supportlists]-->3. <!--[endif]-->書上還提到屬性的其他應用,例如:通過介面來實現在乙個類中同時提供唯讀屬性以及非唯讀屬性。但是我個人認為,雖然這樣可以實現,但是會產生歧義,即在乙個類中提供兩個不同版本的屬性,破壞了類的一致性,所以我並不推薦這麼做。

接著,要說說編寫屬性的時候,需要注意些什麼,我個人認為有如下兩點大的方面。

第乙個就是編寫屬性get部分的時候,如果當前屬性的型別是引用型別的話,且不想通過屬性來修改區域性成員的話,最好返回區域性成員的copy,而不是成員本身。

例如:public class class1

public string data

set}

}public class class2

}public string data

}public class2( string data )

}如果按照如上所寫,那麼class2物件可以通過class1.data屬性訪問和修改區域性成員myclass1某些值,這樣就可以修改了myclass2的私有成員myclass1的值,即會產生潛在錯誤。

例如:class1 myclass1 = myclass2.class1;

myclass1.data = "test2";

如何避免這類錯誤呢,那麼首先需要修改class1屬性的編寫,其次在class1類需要提供clone函式或者其他copy函式,具體如下:

public class class1:icloneable

public string data

set}

#region icloneable members

public object clone()

#endregion

}public class class2

}public string data

}public class2( string data )

}第二個需要注意的是編寫屬性set部分的時候,這裡需要對引數進行有效性檢查。因為屬性是外界修改類的私有成員的入口,為了避免因為私有成員不正確而產生的錯誤,所以在進行屬性set的時候要進行有效性檢查,從而保證私有成員對於整個類來說是有效的。

那麼在實際應用當中,與屬性密切相關的就是實現兩個窗體之間資料訪問,這可能是寫winform程式最基本的。不過很遺憾的是,網上在回答此類問題的時候,很多人都建議用第一種方法來解決。

C 之友元函式不能訪問類的私有成員

無法解決的問題 類中宣告,類外定義的成員函式,導致無法訪問類中的私有成員函式 去掉using namespace std 改變 include 啥的都沒用 蒼了個天,走過路過的幫個忙?學c 嗎,令人頭禿的那種,呵呵 include using namespace std template class...

訪問C 類物件中私有成員變數的方法

原則上,c 類中私有變數不允許在類之外的其他任何地方訪問,一般來說功能完善的類都會提供 get,set 方法來操作類屬性值,但如果沒有 get set方法都沒有提供,比如使用的是第三方提供的 o 或者動態庫 來進行開發的,並且實際應用中我們確確實實需要改變其中某個物件的乙個私有引數,有沒有什麼辦法呢...

c 中類外訪問乙個類的私有成員

正常來說,類外無法訪問類內的private成員,只能通過類內成員訪問private成員,在類外,無論是通過類指標還是類物件都無法直接訪問類中的private成員 c 類中的私友成員是不能通指標操作的。include using namespace std class a int main void ...