new關鍵字
在C++中,內存分為棧和堆。棧中的對象生命周期較短,往往在作用域結束后就會銷毀,而堆中的對象生命周期較長,只有當使用delete或者程序結束時才會銷毀。而new則是將我們創建的對象分配到堆中,使對象可以跨作用域使用。
類成員
部分引用類型的類成員就會用到new,例如String中的char*指針,這樣類就可以處理不同長度的字符串,而不是在類設計時固定一個數組的長度,但是在類構造中使用new一定要記得釋放和同步,如果構造函數中使用new則在析構函數用要使用delete。
String::String(){ stp = new char[length + 1];}
String::~String(){ delete stp; stp = NULL;}
?
類的賦值運算符和復制構造函數
這個還挺重要的,因為在C++中不使用new也可以創建類對象,但是是分配在棧中的,這樣在使用指針的時候就會出現一些問題。
String function(String?stp){
String myString;? //隱式調用默認構造函數在棧中創建一個myString對象?
stp = myString;
return stp;
}? ? //當該作用域結束時,該對象會被銷毀,而其也會相應的調用其析構函數
在上述例子中,我們是可以獲得一個返回的String對象的,但是當調用其中的指針讀取字符時則會出現問題,首先:
1.當需要賦值時會創建一個臨時變量,然后調用復制構造函數將myString對象中的成員對象復制到臨時變量中。
2.在使用復制構造函數時,只會簡單的進行淺拷貝,對于基本類型是值拷貝,而引用類型則是地址的拷貝。
3.賦值運算符還是會進行一次對象的賦值,所以還需要重寫賦值運算符,因為不清楚程序是否會調用還是保險為好。
當使用stp = myString;時
可能會用到復制構造函數,也可能用到賦值運算符,在這種情況下可以使用兩者都進行重寫。
重寫復制構造函數:
Class_name(const Class_name&);
重寫賦值運算符:
Class_name& Class_name::operator=(cosnt Class_name&);
例子:
String(const String& str){
? ? ? ? delete[] this->stp;
? ? ? ? this->stp = new char[length + 1];
????????for(int i = 0; i < size;i++){
? ? ? ? ? ? ? ? ? ? ? ? this->stp[i] = str.stp[i];
????????}
}
使用上述構造函數和賦值運算的重寫,將類對象中的引用類型進行值的拷貝,這樣當賦值時臨時對象的銷毀就不會引起空指針或者內存泄漏的問題。
成員初始化列表
?C++構造函數提供了一種可以用來初始化數據成員的特殊語法,就是使用成員初始化列表。
語法:
String::String(int qs):qSize(qs),items(0),front(NULL),real(NULL){
????????????????????????
}
這種方式可以初始化非靜態的const對象。
或者直接在類中定義初始化
class String{
? ? ? ? private:
? ? ? ? enum{Q_SIZE = 10};
? ? ? ? Node* front = NULL;
? ? ? ? int items?= 0;
? ? ? ? const int qSize = Q_SIZE;
}
?
自動應用類型轉換
?將一個標準類型變量賦給另一種標準類型變量時,如果兩者類型兼容,則C++自動將這個值轉換為接收變量的類型。
只接受一個參的構造函數才能作為轉換函數。
String(double db);
String(int i);
String(char a);
當聲明以上構造函數時,使用下面方式會進行隱式的調用對應的構造函數,將其他類型轉為String類型對象.
String a = 1;? //調用形參為int的構造函數
String b = 23.2;? //double?
function(String str);
function(1);? //也會轉換為String對象
但是這樣會產生一部分問題,當并不想隱式的執行轉換函數時,需要使用explicit關鍵字來關閉這種自動特性。
explicit String(int i);? //不能隱式的作為轉換。?
String a = 1? //錯誤,不能使用隱式轉換
String a = (String)1;? //正確
String a = String(1);??//正確
類構造器也支持自動轉換,允許可以轉型的對象進行自動的轉換.
例如,只持有一個double型參的構造函數:
?String(double db);
String a = 1;? //將int類型轉換為double類型然后創建對象。
但是自動轉換不能有二義性,如果String構造函數中還存在其他可以由int轉型的類型如long,則會出現錯誤,編譯器將提示錯誤。
轉換函數
?既然可以將其他類型轉換為類對象,也可以將類對象轉換為特定的一種類型,需要使用到轉換函數。
需要注意的是:
1.轉換函數為類方法
2.不允許有返回類型
3.不能有型參
語法:
operator double();
例子:
explicit operator int(){? //使用explicit關鍵字,防止隱式轉化
? ? ? ?int length = this->size;? ?
? ? ? ? int sumNum = 0;
? ? ? ? int dig = 1;
? ? ? ? for(int i = 0; i < length; i++){
? ? ? ? ? ? ? ? sumNum += (this->stp[i] - '0') * dig;
? ? ? ? ? ? ? ? dig *= 10;? ? ? ? ? ?
????????} ? ??
? ? ? ? return sumNum;
}
在上述例子中,將字符數組中的數字進行計算,得出了一個int值,實現了將String對象轉換為int類型。?