C++空類默認函數

***************************************************

更多精彩,歡迎進入:http://shop115376623.taobao.com

***************************************************


定義一個空的C++類,例如

class Empty
{
}

一個空的class在C++編譯器處理過后就不再為空,編譯器會自動地為我們聲明一些member function,一般編譯過去就相當于

class Empty
{
public:
Empty(); // 缺省構造函數
Empty( const Empty& ); // 拷貝構造函數
~Empty(); // 析構函數
Empty& operator=( const Empty& ); // 賦值運算符
Empty* operator&(); // 取址運算符
const Empty* operator&() const; // 取址運算符 const
};

一般的書上好像都是前面四種:默認構造函數,拷貝構造函數,默認賦值函數以及析構函數,后面兩種其實屬于,但要需要注意的是,只有當你需要用到這些函數的時候,編譯器才會去定義它們。

如果你只是聲明一個空類,不做任何事情的話,編譯器會自動為你生成一個默認構造函數、一個拷貝默認構造函數、一個默認拷貝賦值操作符和一個默認析構函數。這些函數只有在第一次被調用時,才會別編譯器創建。所有這些函數都是inline和public的。

默認的析構函數是非虛函數(除非基類有自己聲明的虛析構函數)。而拷貝默認構造函數和默認拷貝賦值操作符知識是單純將來源對象的每一個非靜態成員拷貝到對象目標中(bitwise copy)。

其中的默認拷貝賦值操作符只有在生成的代碼合法并且有機會證明它有意義存在時才會生成。這就說明,如果你打算在一個“內含引用成員”或者“內含const成員”的類內支持賦值操作,就必須定義自己的默認拷貝賦值操作符。因為C++本身不允許引用改指不同的對象,也不允許更改const成員。

最后一種情況,當基類將自己的默認拷貝賦值操作符聲明為private時,子類就不會產生自己的的默認拷貝賦值操作符。因為假如產生了這樣的默認拷貝賦值操作符,它會試著去調用基類的默認拷貝賦值操作符去處理基類的部分,不幸的是,它沒有權利。

你可以將拷貝構造函數或默認拷貝賦值操作符聲明為private。這樣明確聲明一個成員函數,就阻止了編譯器暗自創建的默認版本,而這些函數為private,使得可以成功阻止人們調用它。

上面的做法有一個隱患,因為類自身的member和friend還是可以調用這些private函數。有一個很刁鉆的方法,“將成員函數聲明為private而且故意不實現它們”,這樣既阻止了默認函數的生成,而且如果你試著調用這些函數,就會得到一個鏈接錯誤。只聲明,不定義,鏈接器報錯。甚至在聲明的時候,你連參數也不用寫。

而試著將上述的鏈接器錯誤提前到編譯器也是可以的。我們專門設計一個類Unconpyable。
--------------------------------------------------------------------
class Uncopybale {
protected:
????Uncopyable() {}
????~Uncopyable() {}
private:
????Ucopyable(const Uncopyable&)
????Uncopyable& operator=(const Uncopyable&)
};
--------------------------------------------------------------------
為了阻止對象被拷貝,我們唯一需要做的就是繼承Uncopyable。這些函數的默認生成版本會嘗試調用其基類的對應版本,那些調用會被編譯器拒絕,因為它基類的拷貝函數是private。

Boost提供的noncopyable類也有類似的功能。

忠告:

為了駁回編譯器自動提供的技能,可將相應的成員函數聲明為private并且不予實現。使用像Uncopyable這樣的基類也是一種做法。
C++】使用對象前請先正確初始化 ——《Effective C++》讀書筆記3
2009-03-15 06:28
并不是所有的編譯器都包成對象的內置類型成員會被自動初始化為0。永遠在使用對象之前先將它初始化。確保每一個構造函數都將對象的每一個成員初始化。

別把賦值錯當成初始化。C++規定,對象的成員變量的初始化動作發生在進入構造函數本體之前(對于內置類型對象可能不確定),這點對于非內置類型對象來說尤其關鍵。如果你沒有在成員初始化列表(member initialization list)為其初始化,它們將調用自己的默認構造函數,然后才進入構造函數內部(很可能你會在這里給他們賦值)。在成員初始化列表中的初始化只是調用了拷貝構造函數一次,而在構造函數內部再為其賦值則在調用默認構造函數后又調用了一次拷貝構造函數。哪個效率高你當然知道。

所以,請用成員初始化列表進行初始化,雖然效率提高只針對于非內置類型成員,但是規定總是在初值列中雷楚所有成員變量,這樣就省的有些未被列出的內置類型成員被忘記初始化。而有些時候,即使成員變量是內置類型,也必須要用成員初始化列表(成員變量為const或者reference,它們一定要有初值,而且不能被賦值)。

總之,總是使用成員初始化列表,這樣或者必要,或者高效。有個例外,當你重載多個構造函數,每個構造函數有很多成員變量和基類的時候(這意味這成員初始化列表會很多、很長而且重復較多),可以將一些內置類型變量的初始化動作(它們的賦值和初始化不影響效率)移到一個私有函數中,供所有的構造函數調用。

規定:初始化順序是基類早于派生類,類成員變量則以其聲明順序為準。所以成員初始化列表中列出的各個成員的順序最好與聲明的順序相同。

最后說個不常見的問題:某個對象A的非靜態成員變量初始化動作正好使用了另外一個編譯單元(另外一個cpp)中的某個非靜態對象B,你不能保證A在需要B的時候,B就已經被編譯好而且產生了。解決的辦法是將對象A和對象B都分別放到函數中(貌似是專門為每個這樣的對象定制的對象),并且聲明為static。這些函數返回的是靜態對象的引用。這是單例模式的一種實現。在程序中以前需要對象引用的地方直接調用這些函數就好了。這種reference-returning函數對于處理多線程環境下的“競速形勢(race conditions”的方法是:在程序的單線程啟動階段手工調用所有的reference-returning函數。

忠告:

1 為內置對象進行手工初始化,因為C++不保證初始化它們。

2 構造函數最好使用成員初始化列表(member initialization list),而不要在構造函數本體內使用賦值操作。初始化列表列出的成員變量,其排列次序應該和它們在class中的聲明次序相同。

3 為免除“跨編譯單元的初始化次序”問題,請以local static對象替換non-local static對象。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/458861.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/458861.shtml
英文地址,請注明出處:http://en.pswp.cn/news/458861.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

拼接SQL的一個技巧

2019獨角獸企業重金招聘Python工程師標準>>> 為了避免判斷是否要在字符串中加 AND 來連接查詢條件,我們可以直接在在WHERE 后面寫 id>0。 這樣,我們在拼接條件的時候,就可以直接寫 AND 了。 SELECT* FROM t_table WHEREid>0…

【Linux導論】Linux引導流程(The Boot Process)

原文 LFS101x.2 Introduction to Linux (Linux Foundation) Chapter 03: Linux Structure and Installation - Section 2: The Boot Process 引導流程 - (The Boot Process) 你是否想過,在你按下電源開關直至Linux登陸提示出現時,后臺到底發生了哪些事&a…

String類 寫出類的成員函數實現

*************************************************** 更多精彩,歡迎進入:http://shop115376623.taobao.com *************************************************** 已知String類定義如下: class String { public: String(const char *str …

android 管理類,android 線程管理類

1. 延時任務以及取消延時的應用場景:實時搜索,文字內容變化時候不發送請求,當停止變化指定時間后再發送請求2. 使用方法:// 回到主線程MainThreadHelper.runOnUIthread(new Runnable() {Overridepublic void run() {// pushActivi…

計算一行文本的高度

計算一行文本的高度 說明 有時候我們需要知道指定的幾行文本的高度,此工具用于解決此種問題。 源碼 // // NSStringLabelWidthAndHeight.h // ZiPeiYi // // Created by YouXianMing on 15/12/9. // Copyright © 2015年 YouXianMing. All rights reserved.…

python筆記-python編程優化:常用原則和技術介紹

本人翻譯自《Exper Python Programming》 Premature optimization is the root of all evil in programming -Donald Knuth 優化的三原則 讓它跑起來先一個非常常見的錯誤就是在編寫代碼之初我們就開始對代碼進行優化。讓人傷心的是這通常做的都是無用功,很多軟…

C++成員函數重載、覆蓋和隱藏的區別

*************************************************** 更多精彩&#xff0c;歡迎進入&#xff1a;http://shop115376623.taobao.com *************************************************** C成員函數重載、覆蓋和隱藏的區別class Base{public:void Walk(int x){ cout <<…

用fputc()函數以字符串形式寫入字符到磁盤文件

2019獨角獸企業重金招聘Python工程師標準>>> #include <stdio.h> #include <stdlib.h>int main(){FILE *fp;char ch;if((fpfopen("testfile", "a")) NULL){fprintf(stderr, "Error opening file.\n",fp);exit(1);}print…

android 浮動文字提示,Android實現自由拖動并顯示文字的懸浮框

項目中需要實現一個狀態顯示的懸浮框&#xff0c;要求可以設置兩種模式&#xff1a;拖動模式和不可拖動模式。實現效果圖如下&#xff1a;實現步驟&#xff1a;1.首先要設置該懸浮框的基本屬性&#xff1a;/*** 顯示彈出框** param context*/SuppressWarnings("WrongConst…

Android4.2.2的Stagefright維護編解碼器的數據流

這里是他們自己的源代碼閱讀點滴總結屬性&#xff0c;轉請注明出處&#xff0c;謝謝。歡迎和大家分享。qq:1037701636 email:gzzaigcn2012gmail.comAndroid源代碼版本號Version&#xff1a;4.2.2; 硬件平臺 全志A31前沿&#xff1a;在前面的博文中&#xff0c;基本提到的是stag…

PHP的安裝

PHP的環境也是諸多服務器軟件的必要因素之一&#xff0c;它是一個HTML內嵌式語言&#xff0c;在服務器端執行。由于PHP的開源高效化平臺&#xff0c;所以搭建一個php環境是一個運維工程師必備的能力。現在lamp也有類似lnmp.org那種一鍵安裝包&#xff0c;地址是http://yumlamp.…

android 橫向鋪滿,Android開發全程記錄(八)——設置ImageView顯示的圖片鋪滿全屏(適應魅族等不常見屏幕比例)...

為適應不同屏幕的手機&#xff0c;ImageView顯示的圖片可能不鋪滿屏幕&#xff0c;如果定高的話&#xff0c;兩邊可能會出現空白。魅族手機就會有這種情況&#xff0c;在其他手機里顯示正常&#xff0c;在魅族手機里顯示&#xff0c;圖片左右兩邊會出現空白&#xff0c;為解決這…

tihs 關鍵字

//this關鍵詞/*調用類中的屬性 調用類中的方法或構造方法 調用當前對象&#xff0c;調用自己的方法&#xff0c;可以省略。 */ //http://blog.sina.com.cn/s/blog_71f6c1980100wtj4.html//this指當前對象自己public class Google{String s"hello";public Google(Stri…

良好的編程習慣

*************************************************** 更多精彩&#xff0c;歡迎進入&#xff1a;http://shop115376623.taobao.com *************************************************** 良好的編程習慣良好的習慣對于人的成長是非常重要的&#xff0c;良好的編程習慣對于我…

ntfs for mac使用注意事項有哪些?

2019獨角獸企業重金招聘Python工程師標準>>> mac的用戶有很多&#xff0c;一些用戶朋友會發現自己的電腦是無法讀寫ntfs驅動器的。而ntfs驅動器又是一種常用的驅動器。面對這種情況我們可以選擇用NTFS for Mac軟件來幫助我們&#xff0c;它可以讀寫ntfs驅動器&#…

android音樂播放器文章,Android復習09【內容提供者、音樂播放器】

目 錄PersonCpPersonCp.javainsert()ContentObserver音樂播放器1、添加讀寫權限1.1、動態權限授予(調用封裝好的方法)2、獲取音樂文件(MainActivity.java)2、Music.java(實體類)申請訪問SD卡的權限設置適配器下拉刷新PersonCpPersonCp.javapackage cn.wangzg.personcp;import a…

程序員的業余項目

程序員的業余項目&#xff0c;我們也叫它 side project。 前幾天&#xff0c;100offer 發起了一場活動叫 <尋找實干和堅持的技術力量>&#xff0c;他們是這么說的&#xff1a; 世界在被代碼改變著&#xff0c;而我們在創造著代碼。 僅僅是因為好玩&#xff0c;他開發了…

C語言的數組名和對數組名取地址

*************************************************** 更多精彩&#xff0c;歡迎進入&#xff1a;http://shop115376623.taobao.com *************************************************** 相信不少的C語言初學者都知道&#xff0c;數組名相當于指針&#xff0c;指向數組的首地…

小米 android 8,小米華為們誰最良心?10大手機廠商安卓8.0升級情況盤點

3月8日&#xff0c;谷歌放出了首個安卓9.0開發者預覽版的固件包&#xff0c;不出意外的話&#xff0c;它的正式版會在今年正式亮相。但對廣大安卓用戶來說&#xff0c;想要立刻用上最新系統并非易事。目前來說&#xff0c;安卓碎片化問題依然嚴重&#xff0c;我們不妨現實點&am…

窺探Swift之數組安全索引與數組切片

在Swift中的數組和字典中下標是非常常見的&#xff0c;數組可以通過索引下標進行元素的查詢&#xff0c;字典可以通過鍵下標來獲取相應的值。在使用數組時&#xff0c;一個常見的致命錯誤就是數組越界。如果在你的應用程序中數組越界了&#xff0c;那么對不起&#xff0c;如果由…