1、this指標與類與對象的記憶體結構分布
1)this指標定義在類的方法中
2)是隱性的指標
3)建立類對象之後,this指標沒有具體指向哪裡,如果不調用類的方法,,this指標不會指向操作函數。
當類對象調用類的方法去操作本身記憶體空間時,this指標會指向這個類的對象。
4)是屬於類的唯一的一個指標,在對不同的類對象操作時會即時切換。
app.h
#ifndef APP_H
#define APP_H
#include <iostream>
using namespace std;
class point
{
private:
int x;
int y;
public: //操作方法一般都設為公有,被外部函數調用
//普通的類的成員函數
void setxy(int a,int b)
{
this->x=a; //this指標是隱藏的,可以不用寫
this->y=b;
}
void disxy()
{
cout<<"x= "<<x<<endl;
cout<<"y= "<<y<<endl;
}
};
#endif // APP_H
類是存在test段,
main.cpp
#include"app.h"
int main()
{
cout << "Hello World!" << endl;
point p; //分配一段記憶體空間,沒有內容,需要初始化
p.setxy(18,27);
p.disxy();
return 0;
}
p是個資料類型,局部變數。執行point p語句根據類的資料成員為p分配記憶體空間。可以用size查看空間大小。
p.setxy是一個代碼的起始地址。
2、構造與折構函數(拷貝構造)
2.1建構函式:是用來對類的對象的記憶體中的變數進行初始化
#include <iostream>
using namespace std;
class point
{
private:
int x;
int y;
public:
//定義了一個類的建構函式,用於初始化
point (int a,int b)
{
cout<<"constructor"<<endl;
x=a;
y=b;
}
/*
void setxy(int a,int b)
{
this->x=a;
this->y=b;
}*/
void disxy()
{
cout<<"x= "<<x<<endl;
cout<<"y= "<<y<<endl;
}
};
int main()
{
cout << "Hello World!" << endl;
point p(20,90); //直接調用類的建構函式
//p.setxy(18,27);
p.disxy();
return 0;
}
輸出: constructor
x=20
y=90
特點:1)定義的建構函式,會對類對象建立時自動調用構造對對類對象成員進行初始化
2)函數名跟類名要一樣
3)沒有傳回值
4)如果定義在類外,也要加上類從屬關係
5)建構函式可以重載(函數名一樣,但傳參不同)
何為重載:樣本
point()
{
cout<<"no param"<<endl;
x=66;
y=45;
}
point(int a)
{
cout<<"one param"<<endl;
x=a;
y=88;
}
point (int a,int b)
{
cout<<"constructor"<<endl;
x=a;
y=b;
}
point p;
p.disxy();
建立類對象的時候會在類中尋找構建函數,如果沒有定義建構函式,系統會自動分配一個無傳參的建構函式。啟動並執行時候不會報錯。如果有,傳參不一樣會出現報錯。
2.2解構函式:對已經存在的類對象的記憶體進行清除處理
~point()//在類裡面定義解構函式
{
cout<<"clean all"<<endl;
}
1)無傳參,無傳回值,但是要帶一個“~”聲明是析構
2)每調用一次建構函式建立一個類對象,就一定會在退出前自動調用解構函式來清除這個對象記憶體。
3)如果類沒有定義解構函式,系統也會自動分配一個解構函式。
2.3拷貝建構函式
1)將一個變數的內容拷貝過程,初始化到新的變數的過程
類裡面定義拷貝建構函式
point(const point &p)
{
cout<<"copy construnstor"<<endl;
x=p.x+11;
y=p.y+44;
}
point p2 = p1; 或者point p2(p1);都是調用了上面的函數
2.4深淺拷貝建構函式
1)淺拷貝vs深拷貝
char *pdest; //指標指向一塊記憶體位址,可能有內容。(類成員)
main.cpp:point p2 = p1; //拷貝函數
// 定義一個拷貝建構函式 point(const point &p) { cout<<"copy constructor"<<endl; xres = p.xres; yres = p.yres; //會使得p1與p2共用到同樣一塊記憶體,這種做法稱為淺拷貝構造 //調試1: //pDest = p.pDest; //深拷貝做法 //調試2: pDest = new char[strlen(p.pDest) + 1]; if(pDest != 0) { strcpy(pDest, p.pDest); } }
//解構函式需要釋放記憶體
~point()
{
cout<<"clean all"<<endl;
delete pdest;
}
淺拷貝隱藏bug,很少使用。
3、初始化列表
3.1類成員函數的實現
通過類對象調用類的成員函數,實現初始化。
p.setxy();
3.2建構函式實現
//用於初始化的建構函式
point (int a,int b):x(a),y(b){} //這樣的形式,效率比較快
建立類對象時自動調用建構函式,實現初始化。
a.一個是構造,一個是普通成員函數
b.建構函式在分配記憶體空間的就初始化,而成員函數是先定義一個類的對象分配記憶體空間,再對成員初始化,頻率是不一樣的。
特點:更快實現對類對象的各個變數初始化
什麼情況下會使用初始化列表。
1.使用const聲明的變數要初始化、
2.使用引用聲明的變數要初始化
const int x;
3.衍生類別中要對基類部分內容進行初始化
class space:public point
{
private:
int z;
public:
void setz(int c);
}
space::space(int c):point(x,y)
{
z = c;
}
4、關鍵字分析
4.1static關鍵字
1)可以用於聲明類的資料成員
class point
{
private:
int x; //非待用資料成員
static int y; //待用資料成員
}
如果static聲明後,編譯器會在編譯時間將這個變數串連到data段。
好處:在編譯階段就會被處理(分配得到自己的空間);
放到data段,在載入後是獨立存在的段,被所有的程式都可以訪問到,相當於全域變數。
如何使用:
類外初始化
用static聲明
可以直接使用:如果是private聲明,只能通過類的公有函數操作;如果是public聲明,可以直接通過類調用,也可以通過類的公有函數操作。
#ifndef INIT_H
#define INIT_H
#include<iostream>
#include<string>
using namespace std;
class computer
{
private:
float unit_price; //非靜態成員函數
//static float total_price; //靜態成員函數
public:
static float total_price;
computer(int price)
{
unit_price = price;
total_price += price;
}
void disinfo()
{
cout<<"unit_price = "<<unit_price<<endl;
cout<<"total_price = "<<total_price<<endl