C 寒假學習 類和物件

2021-10-01 21:57:24 字數 4997 閱讀 9550

1. c++記憶體布局分為幾個區域,各自具備什麼特點?

在c++中,程式在記憶體中的儲存被分為五個區:

1)、棧區(stack):由編譯器自動分配釋放 ,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧。

2)、堆區(heap):一般由程式設計師分配釋放,若程式設計師不釋放,程式結束時可能由os**。注意它與資料結構中的堆是兩回事,分配方式倒是類似於鍊錶。

3)、全域性/靜態區(static):全域性變數和靜態變數的儲存是 放在一塊的,在程式編譯時分配

4)、文字常量區:存放常量字串

5)、程式**區:存放函式體(類的成員函式、全域性函式) 的二進位制**

2. 當定義類時,編譯器會為類自動生成哪些函式?這些函式各自都有什麼特點?

對於乙個空類,c++編譯器預設生成四個成員函式:預設建構函式、析構函式、拷貝(複製)建構函式、賦值函式。

1)、預設建構函式(default constructor):

在沒有顯式提供初始化式時呼叫的建構函式。它由不帶引數的建構函式,或者為所有的形參提供預設實參的建構函式定義。如果定義某個類的變數時沒有提供初始化式就會使用預設建構函式。如果使用者定義的類中沒有顯式的定義任何建構函式,編譯器就會自動為該型別生成預設建構函式,稱為合成的建構函式(synthesized default constructor)。c++語言為類提供的建構函式可自動完成物件的初始化任務。全域性物件和靜態物件的建構函式在main()函式執行之前就被呼叫,區域性靜態物件的建構函式是當程式第一次執行到相應語句時才被呼叫。然而給出乙個外部物件的引用性宣告時,並不呼叫相應的建構函式,因為這個外部物件只是引用在其他地方宣告的物件,並沒有真正地建立乙個物件。

2)、析構函式:

當程式設計師沒有給類建立析構函式,那麼系統會在類中自動建立乙個析構函式,形式為:~a(){},為類a建立的析構函式。當程式執行完後,系統自動呼叫自動建立的析構函式,將物件釋放。預設的析構函式不能刪除new運算子在自由儲存器中分配的物件或物件成員。如果類成員占用的空間是在建構函式中動態分配的,我們就必須自定義析構函式,然後顯式使用delete運算子來釋放建構函式使用new運算子分配的記憶體,就像銷毀普通變數一樣。

3)、拷貝建構函式:

如果不主動編寫拷貝建構函式和賦值函式,編譯器將以「位拷貝」的方式自動生成預設的函式。倘若類中含有指標變數,那麼這兩個預設的函式就隱含了錯誤。

以類string的兩個物件a,b為例,假設a.m_data的內容為「hello」,b.m_data的內容為「world」。

現將a賦給b,預設賦值函式的「位拷貝」意味著執行b.m_data = a.m_data。這將造成三個錯誤:

a、b.m_data原有的記憶體沒被釋放,造成記憶體洩露;

b、b.m_data和a.m_data指向同一塊記憶體,a或b任何一方變動都會影響另一方;

c、在物件被析構時,m_data被釋放了兩次。

拷貝建構函式的呼叫時機:

a. 當把乙個已經存在的物件賦值給另乙個新物件時,會呼叫拷貝建構函式。

b. 當實參和形參都是物件,進行實參與形參的結合時,會呼叫拷貝建構函式。

c. 當函式的返回值是物件,函式呼叫完成返回時,會呼叫拷貝建構函式。

4)、賦值函式:

每個類只有乙個賦值函式。拷貝建構函式和賦值函式非常容易混淆,常導致錯寫、錯用。拷貝建構函式是在物件被建立時呼叫的,而賦值函式只能被已經存在了的物件呼叫。

3. 什麼是淺拷貝, 什麼是深拷貝?

淺拷貝是增加了乙個指標,指向原來已經存在的記憶體。而深拷貝是增加了乙個指標,並新開闢了一塊空間讓指標指向這塊新開闢的空間。淺拷貝在多個物件指向一塊空間的時候,釋放乙個空間會導致其他物件所使用的空間也被釋放了,再次釋放便會出現錯誤。

實現乙個自定義的string類,保證main函式對正確執行。 

class string

;int main(void)

#define _crt_secure_no_warnings

#include "stdafx.h"

#include "string.h"

#include //#include "stdio.h"

using std::cout;

using std::endl;

//using std::string;

//傾向於將std::string當成乙個內建型別使用

class point

point(int x,int y)

:_ix(x), _iy(y)

//每個成員在初始化列表之中只能出現一次,其初始化的順序不是由成員變數在初始化列表中的順序決定的,

// 而是由成員變數在類中被宣告時的順序決定的。

point(int val)

:_iy(val),

_ix(_iy)

//拷貝建構函式

point(const point &rhs)

:_ix(rhs._ix),

_iy(rhs._iy)

//析構函式:清理工作

~point()

//在類中定義的非靜態成員函式中都有乙個隱含的this指標,它代表的就是當前物件本身,

// 它作為成員函式的第乙個引數,由編譯器自動補全。

// 比如print 函式的完整實現是:

void print(/*point * const this*/) //這裡的const又是為什麼

private:

int _ix;

int _iy;

//const int _iz;

};class line

void print()

private:

point _pt1;

point _pt2;

};class string

string(const char *pstr)//建構函式

:_pstr ( new char[strlen(pstr) + 1]())

string(const string & rhs)//拷貝建構函式

:_pstr(new char[strlen(rhs._pstr) + 1]())

string & operator=(const string & rhs)//賦值運算子函式

cout << "賦值運算子函式" << endl;

return *this;

} ~string()//析構函式

void print()

private:

char * _pstr;

};class computer

computer(const char * brand, double price) //這裡為什麼要用const?

:_brand ( new char[strlen(brand) + 1]()), //深拷貝

_price(price)

//系統自動提供乙個拷貝建構函式, 固定寫法

//1. 引用符號不能去掉,如果去掉,根據拷貝建構函式的呼叫時機來看,會導致無窮遞迴,直到棧溢位,程式崩潰

//2. const關鍵字不能去掉,如果去掉,當傳遞過來的是右值時,就無法正確呼叫拷貝建構函式

computer(const computer &rhs)

:_price(rhs._price),

_brand(new char[strlen(rhs._brand) + 1]())

computer & operator=(const computer &rhs)

settotalprice();

} void settotalprice()

//由於資料成員_brand指向了堆空間的區域,所以必須要顯式提供乙個析構函式進行**

//析構函式要清理的是物件的資料成員申請的資源,而物件本身所佔據的空間,不是由析構函式來**的

//只要物件被銷毀,就會自動呼叫析構函式

//不建議顯示呼叫析構函式

//只有delete表示式才能**物件佔據的空間

~computer()

void print()

private:

char *_brand;

double _price;

//c++ 允許使用static (靜態儲存)修飾資料成員,這樣的成員在編譯時就被建立並

// 初始化的(與之相比,物件是在執行時被建立的),且其實例只有乙個,被所有該

// 類的物件共享,就像住在同一宿舍裡的同學共享乙個房間號一樣。靜態資料成員和

// 之前介紹的靜態變數一樣,當程式執行時,該成員已經存在,一直到程式結束,任

// 何該類物件都可對其進行訪問,靜態資料成員儲存在全域性 / 靜態區,並不佔據物件的

// 儲存空間。

//一般來說,我們不能在類的內部初始化靜態資料成員,必須在類的外部定義和初始化靜態資料成員,

//且不再包含static 關鍵字,

static double _totalprice;

};//初始化靜態資料成員

//型別 類名::變數名 = 初始化表示式; //普通變數

//型別 類名::物件名(構造引數); //物件變數

double computer::_totalprice = 0;

int testpoint(void)

int testline(void)

int teststring(void)

int testcomputer(void)

//main函式退出之後,全域性物件會自動被銷毀

//computer com6("thinkpad", 8888);

int main(void)

特殊資料成員的初始化

常量資料成員const、引用成員、類物件成員、靜態成員

1.常量成員只能在建構函式初始化列表中初始化

2.引用成員也只能在建構函式初始化列表中初始化

3.類物件成員也只能在建構函式初始化列表中初始化

4.靜態成員初始化

寒假打卡類和物件

類和物件 過程性程式設計 oop物件導向程式設計 過程性程式設計 例如int main 由上至下。考慮遵循的步驟,如何表示資料。oop 首先考慮資料不僅要考慮如何表示資料,還要考慮如何使用資料。基本資料單元 抽象和類 以小狗作為例子 抽象 提取主要資訊,去除次要不關鍵資訊建立模型 屬性 一類事物的特...

C 學習 類和物件

1 類的訪問控制有哪些?公有成員 以關鍵字public指明。私有成員 以關鍵字private指明。保護成員 以關鍵字protected指明。2 拷貝建構函式的作用是什麼?用乙個已經存在的物件初始化本類的新物件。3 友元函式和友元類的作用是什麼?友元提供了不同類或物件的成員函式之間 類的成員函式與一般...

C 學習 類和物件

10.2.1 建構函式 建構函式就是建立乙個物件,完成對其的初始化工作,賦值操作就在初始化中完成。class cperson int main cperson即為建構函式 10.2.2 複製建構函式 複製建構函式就是用乙個已經初始化的物件生成乙個一模一樣的物件。class cperson cpers...