一、變數
1、變數和類的生命周期
變數的生存期是指變數所占據的記憶體空間由分配到釋放的時期,變數有效的范圍稱為其作用域,全域變數是程式中定義在所有函式(包括main函式)之外的任何變數,其作用域
是程式從變數定義到整個程式結束的部分,這意味著全域變數可以被所有定義在全域變數之后的函式訪問,全域變數及靜態變數分配的空間在全域資料區,它們的生存期為整個程式的執行期間,
? 而區域變數,如在函式內或程式塊內說明的變數,被分配到區域資料區,如堆疊區等,這種分配是臨時的,一旦該函式體或程式塊運行結束,所分配的空間就會被撤銷,區域變數的生存期從被說明處開始,到所在程式塊結束處結束,
? 對于靜態變數,如果沒有進行初始化,系統會自動初始化為0,區域變數如果沒有進行初始化,則其值是不確定的,
? 使用new運算子創建的變數具有動態生存期,從宣告處開始,直到用delete運算子釋放存盤空間或程式結束時,變數生存期結束,類的物件在生成時呼叫建構式,在消亡時呼叫解構式,在這兩個函式呼叫之間即是物件的生存期,
2、在類中,也可以使用const關鍵字定義成員變數和成員函式,甚至是類的物件,由關鍵字const修飾的類成員變數稱為類的常量成員變數,類的常量成員變數必須進行初始化,而且只能通過建構式的成員初始化串列的方式進行,使用const修飾的函式稱為常量函式,定義類的物件時如果在前面添加const關鍵字,則該物件稱為常量物件,定義常量物件或常量成員變數的一般格式如下:
const 資料型別 常量名=運算式;
? 定義常量函式的格式如下:型別說明符 函式名(引數表)const;
? 在物件被創建以后,其常量成員變數的值就不允許被修改,只可以讀取其值,對于常量物件,只能呼叫常量函式,總之,常量成員變數的值不能修改,常量物件中的各個屬性值均不能修改,
? 不能通過常量物件呼叫普通成員函式 const Person person;person.getName();//錯誤的
一、封閉類
當生成封閉類的物件并進行初始化時,它包含的成員物件也需要被初始化,需要呼叫成員物件的建構式,在定義封閉類的建構式時,需要添加初始化串列,指明要呼叫成員物件的哪個建構式,在封閉類建構式中添加初始化串列的格式如下:
封閉類名::建構式名(引數表): 成員變數1(引數表),成員變數2(引數表),…{…}
初始化串列中的成員變數既可以是成員物件,也可以是基本資料型別的成員變數,對于成員物件,初始化串列的“引數表”中列出的是成員物件建構式的引數(它指明了該成員物件如何初始化),
先呼叫成員物件的建構式,再呼叫封閉類物件的建構式,
2、封閉類的復制建構式
如果封閉類的物件是用默認復制建構式初始化的,那么它包含的成員物件也會用復制建構式初始化,
//成績類 class Course{ public: int id; string name; Course(); Course(Course &course); Course(int id,string name); }; Course::Course(Course &course){ cout << "Course 復制建構式" << endl; this->id=course.id; this->name=course.name; } Course::Course(int id,string name){ this->id=id; this->name=name; cout << "Course 普通建構式" << endl; }; //學生類 class Student{ public: int id; string name; //學生類中包含課程(Course),Student 稱為封閉類 Course course; Student(int id,string name,int cId,string cName); void show(); }; Student::Student(int id,string name,int cId,string cName):id(id),name(name),course(cId,cName){ cout << "Student 普通建構式" << endl; } void Student::show(){ cout << "name:" << this->name <<" course:" << this->course.name<< endl; } int main(){ Student student(1,"小米",1,"數學"); student.show(); Student student2(2,"美團",1,"C++"); student2.show(); }
三、this指標
C++語言規定,當呼叫一個成員函式時,系統自動向它傳遞一個隱含的引數,該引數是一個指向呼叫該函式的物件的指標,稱為this指標,從而使成員函式知道對哪個物件進行操作,
? C++規定,在非靜態成員函式內部可以直接使用this關鍵字,this就代表指向該函式所作用的物件的指標,
? 在一般情況下,在不引起歧義時,可以省略“this->”,系統采用默認設定,
? 靜態成員是類具有的屬性,不是物件的特征,this表示的是隱藏的物件的指標,所以靜態成員函式沒有this指標,
void Person::setName(string name){ this->name=name; } string Person::getName(){ return this->name; } void Person::setId(int id){ this->id=id; } int Person::getId(){ return this->id; }
四、物件的性質
1、同一類的物件之間可以相互賦值,
如陳述句:Point A,B; A.Setxy(25,55); B=A;
2、可以使用物件陣列,
如陳述句:Point A[3]; 定義陣列A可以存盤3個Point類的物件,
3、也可以使用指向物件的指標,使用取地址運算子&將一個物件的地址置于該指標中,
如陳述句: Point * p=&A; p->Display();
4、物件可以用作函式引數,
如果引數傳遞采用傳物件值的方式,會在傳值程序中產生副本,即臨時物件,所以在被呼叫函式中對形參所作的改變不影響呼叫函式中作為實參的物件,
如果采取傳物件的參考(傳地址)的方式,當形參物件被修改時,相應的實參物件也將被修改,如果采用傳物件地址值的方式,則使用物件指標作為函式引數,效果與傳物件的參考一樣,
C++推薦使用物件的參考作為引數傳遞,因為這樣不會產生副本(即臨時物件),在程式執行時不用呼叫建構式,可直接進入函式體執行陳述句,在函式結束后,也不用呼叫解構式析構臨時物件,如想避免被呼叫函式修改原來物件的資料成員,可使用const修飾符,
- void print(Point a){a.Display;} //物件作為函式引數
- void print(Point&a){a.Display;} //物件參考作為函式引數
- void print(Point * p){p->Display;} //物件指標作為引數
它們的原型宣告分別為:print(Point),print(Point&),print(Point *),
對于物件A,print(&A)呼叫的是原型為print(Point *)的函式形式,
另外,函式多載不能同時采用如上3種同名函式,因為函式使用的引數為物件或物件參考時,編譯系統無法區別這兩個函式,多載只能選擇其中的一種,
五、類的使用權限
使用類的權限
①類本身的成員函式可以使用類的所有成員(私有和公有成員),
②類的物件只能訪問公有成員函式,例如輸出x只能使用A.Getx(),不能使用A.x,
③其他函式不能使用類的私有成員,也不能使用公有成員函式,它們只能通過定義類的物件為自己的資料成員,然后通過類的物件使用類的公有成員函式,
④雖然一個類可以包含另外一個類的物件,但這個類也只能通過被包含的類的物件使用那個類的成員函式,通過成員函式使用資料成員,person 是 student的成員,student不能直接操作person中的屬性,只能 Student.person.成員的方式來操作person中的成員
class Person{ public: int id; string name; }; class Student{ public: Person person; }
六、不完全的類的宣告
類不是記憶體中的物理物體,只有當使用類產生物件時,才進行記憶體分配,這種物件建立的程序稱為實體化,
類必須在其成員使用之前先進行宣告,然而,有時也可以在類沒有完全定義之前就參考該類,此時將類作為一個整體來使用,如宣告全域變數指標:
class MembersOnly; //不完全的類宣告 MembersOnly * club; //定義全域變數類指標 Void main(){… 函式體} //主函式 class MembersOnly{…函式體}; //完全定義該類
不完全宣告的類不能實體化,否則會編譯出錯;不完全宣告僅用于類和結構,企圖存取沒有完全宣告的類成員,也會引起編譯錯誤,
七、空類:
盡管類的目的是封裝代碼和資料,它也可以不包括任何宣告,如:class Empty{ }; 這種空類沒有任何行為,但可以產生空類物件,
在開發大的專案時,需要在一些類還沒有完全定義或實作時進行先期測驗,定義空類可保證代碼能正確被編譯,從而允許先測驗其中的一部分,此時常給空類增加一個無引數建構式,以消除強型別檢查的編譯器產生的警告,如
class Empty{
public:Empty(){ }
};
八、類作用域
①宣告類時所使用的一對花括號形成類作用域,在類作用域中宣告的識別符號只在類中可見,如:class example { int num; } ;
int i=num; //定義整型數i,并用num賦值;錯誤,因為num在類外并沒有定義,所以在此不可見
int num; //重新定義整型數num;正確,因為此num是重新定義的一個整型數,與類中說明的資料成員num具有不同的作用域
②如果某成員函式的實作是在類定義之外給出的,則類作用域也包含該成員函式的作用域,因此,當在該成員函式內使用一個識別符號時,編譯器會先在類定義域中尋找,如下例:
class Myclass { int number; //定義屬于類Myclass的整型數number public: void set(int); }; int number; //這個number不屬于類Myclass void Myclass::set(int i){ number=i; //使用的是類Myclass中的識別符號number };
③類中的一個成員名可以通過使用類名和作用域運算子來顯式的指定,稱為成員名限定,例如:
void Myclass::set(int i){
Myclass::number=i; //顯示指定訪問Myclass類中的識別符號number
}
④在程式中,物件的生存期由物件說明來決定;類中各資料成員的生存期由物件的生存期決定,隨物件存在和消失,
⑤使用struct關鍵字設計類與class相反,struct的默認控制權限是public,一般不用struct設計類,而是用struct設計只包含資料的結構,然后用這種結構作為類的資料成員,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/20783.html
標籤:C++
上一篇:C語言程式結構
下一篇:有大神知道這個該怎么辦嗎?
