C++複習封裝(多驗證)
實例化:
從棧實例化對象:系統自動回收
TV tv1;
從堆實例化對象:delete釋放內存
TV *p = new TV();
TV *q = new TV[20];
delete p;
delete []q;
對象成員訪問
棧:對象 加 .
int main()
{
TV tv;
tv.type = 0;
tv.changeVol();
return 0;
}
堆:指針 加 ->
int main()
{
TV *p = new TV();
p->type =0;
p->changeVol();
delete p;
p = NULL;
return 0;
}
String
初始化string對象:
string s1;
string s2(“ANC”);
string s3(s2);
string s4(n,‘c’); 將s4初始化爲字符’c’的n個副本。
常用基礎操作:
s.empty(); 空返回true,否則false
s.size(); 返回s中字符個數
s[n]; 返回s中位置爲n的字符,位置從0開始
s1+s2 返回連接後的新串
s1 = s2 將s1內容替換爲s2的副本
s1 == s2 相等返回true,否則false
字符串常量之間+是非法的,+兩邊必須至少有一個爲string對象
而非常量"xxx"
類內定義和內聯函數
內聯函數:關鍵字inline:編譯時將函數體代碼和實參代替函數調用語句。必須是結構很邏輯比較簡單的代碼,才能保證效率快。
普通函數:main()調用普通函數->找到函數入口->運行函數的代碼->結束後返回到主調函數。
類內定義就是成員函數的定義在類中。類內定義的成員函數(簡單的)會自動看作inline函數。
類外定義是指成員函數的函數體寫在類的外面:
1.同文件類外定義(類定義與成員函數定義在同一個文件中)
需要在每個函數前面用類名 加上 :: 來標識
2.分文件類外定義:
定義一個與類名(Car)相同名字的頭文件(Car.h)
再在Car.cpp中加上#include “Car.h”
實現成員函數的定義同樣是要在每個函數前面用類名 加上 :: 來標識。
內存分區
棧區:定義變量。內存由系統分配。
int x = 0;
int *p = NULL;
堆區:new分配的內存,需要自己管理。
int *p = new int[20];
全局區:存儲全局變量及靜態變量。
常量區:存儲常量
string str = "hello";
代碼區:存儲邏輯代碼的二進制
構造函數
class student
{
public:
Student(){}
Student(string name = "Jim")
private:
string m_strName;
};
int main()
{
Student stu1();
Student *p = NULL;
p = new Student();
return 0;
}
初始化列表:
class student
{
public:
Student():m_strName("Jim"),m_iAge(10){}
private:
string m_strName;
int m_iAge;
};
初始化列表先於構造函數執行。
初始化列表只能用於構造函數。
初始化列表可以同時初始化多個數據成員,速度高,效率快。
初始化列表的必要性:
類中的不變的成員變量(常量,比如PI),必須通過初始化列表。
拷貝構造函數:
定義格式:類名(const 類名& 變量名)
構造函數分爲無參構造函數(默認構造函數)和有參構造函數(分爲參數帶默認值和參數不帶默認值)。
還有相關的小點:
1.深、淺拷貝:
有指針類型的數據成員時,在main中 obj1 = obj2來創建對象對其初始化時需要在類中定義深拷貝構造函數(即需要將指針指向的內存中的變量一一賦值)
2.對象數組
…就是一下定義好多對象唄 new的時候 類名後面不是()而是[n]… n是數組中元素個數
3.對象指針:
指向對象的指針,指針指向的內存就是對象裏第一個數據成員的地址,可以 p->來訪問對象數據成員,也可以用(*p). 來訪問,前者是指針,後者是對象。
4.對象成員指針:
某個類對象的指針作爲另一個類的成員。可以初始化列表進行初始化(直接()裏NULL就行),也可以進行普通的初始化,還可以m_a = new C(1,3);在用其構造函數堆中創建對象,但要注意這種需要在我們的當前類的析構函數里加上delete語句釋放。
5.this指針:
指向對象自身數據的指針。 this指針就是&當前對象。在類中的方法中都隱藏了this指針參數,所以調用的時候也隱藏了this指針,實際上是存在的,由此不會產生對象錯亂的情況。
6.const:
類的數據成員可以用const來修飾,基本數據類型的數據成員用const修飾時,需要用初始化列表來初始化給它一個不變的值。
class Coordinate
{
public:
Coordinate(int x,int y);
private:
const int m_iX;
const int m_iY;
};
Coordinate::Coordinate(int x, int y):m_iX(x),m_iY(y)
{
}
7.常對象成員:
一旦初始化就不能再修改的對象成員。
class Line
{
public:
Line(int x1, int y1, int x2, int y2);
private:
const Coordinate m_coorA;
const Coordinate m_coorB;
};
Line::Line(int x1,int y1, int x2, int y2):m_coorA(x1,y1),m_coorB(x2,y2)
{
}
int main{
Line *p = new Line(2.1.6,4);
delete p;
p = NULL;
return 0;
}
8.常成員函數:
常成員函數中不能修改成員函數的值。
class Coordinate
{
public:
Coordinate(int x, int y);
void changeX() const; //常成員函數和下面這個函數是互爲重載
void changeX();
private:
int m_iX;
int m_iY;
};
void Coordinate::changeX()
{
m_iX = 20;
}
int main()
{
Coordinate coordinate(3,5);
coordinate.changeX(); //調用的是不帶const的成員函數
return 0;
}
函數定義實際上隱藏了this指針,等價於:
void Coordinate::changeX(Coordinate *this)
{
this->m_iX = 20;
}
爲什麼函數類外定義的時候不在後面也加上const呢?
因爲定義時加上const後,this指針就變成了常指針:const Coordinate *this
此時它指向的數據m_iX是不能被修改的,即this->m_iX = 20;會出錯。
怎樣能調用const修飾的成員函數呢?
int main()
{
const Coordinate coordinate(3,5); //定義一個常對象
coordinate.changeX(); //通過常對象調用const修飾的成員函數
return 0;
}
9.常指針,常引用:
在對象指針或對象引用前加上const。
對象引用可以直接賦值初始化,而對象指針需要給賦值對象加一個引用:
Coordinate coor(3,5);
Coordinate &coor2 = coor1;
Coordinate *pCoor = &coor1;
常引用或常指針只有一個讀權限,而getX();函數中隱藏的this要求的是讀寫權限的參數,所以如果coor2.getX();或Pcoor->getY();會報編譯錯誤。想要調用成員函數只能調用printInfo():
Coordinate coor(3,5);
const Coordinate &coor2 = coor1;
const Coordinate *pCoor = &coor1;
如果是下面這樣:
Coordiante * const pCoor = &coor1;
那麼pCoor就只能指向coor1這一個對象,不能指向其他對象。但指針是具有讀寫權限的,所以可以調用getY();