滴水逆向初級-C++(三)

3.1.封裝

一、什麼是封裝:
將函數定義到結構體內部,就是封裝。
二、什麼是類:
帶有函數的結構體,稱爲類。
三、什麼是成員函數:
結構體裏面的函數,稱爲成員函數。c++

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>

struct Student
{
	int a;
	int b;
	int c;

	int plus()
	{
		return a+b+c;
	}
};


void main()
{
	Student s = {1,2,3};
	int r = s.plus();    //r=6
		
	system("pause");
	return ;
}

3.2.this指針

一、什麼是this指針windows

一、this指針是編譯器默認傳入的,一般都會使用ecx進行參數的傳遞。
二、你用或者不用,它都在那。數組

三、this指針不能作++-等運算,不能從新被賦值。
四、this指針不佔用結構體的寬度。函數

二、this指針的使用this

struct sclass
{
	int a;
	int b;
    
	void Init(int a,int b)
    {
		this->a=a;
		this->b= b;
	}
	void Print()
	{
		printf("%d %d" ,a,b);
	}
};

3.3.構造函數與析構函數

一、構造函數設計

一、與類同名,沒有返回值
二、建立對象的時候執行,主要用於初始化
三、能夠有多個(最好有一個無參的),稱爲重載,其餘函數也能夠重載
四、編譯器不要求必須提供指針

二、析構函數總結:
一、只能有一個析構函數不能重載
二、不能帶任何參數
三、不能帶返回值
四、主要用於清理工做
五、編譯器不要求必須提供code

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>

struct Student
{
	int a;
	int b;
	int c;
	
	Student()
	{
		printf("沒有參數的構造函數\n");
	}

	Student(int a,int b,int c)
	{
		this->a = a;
		this->b = b;
		this->c = c;
		printf("有參數的構造函數\n");
	}

	~Student()
	{
		printf("析造函數\n");	
	}

	int plus()
	{
		return a+b+c;
	}
};


void main()
{
	Student s1;
	Student s2(1,2,3);

		
	system("pause");
	return ;
}

3.4.繼承

一、什麼是繼承?
繼承就是數據的複製
二、爲何要用繼承?
減小重複代碼的編寫對象

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>

struct X
{
	int a;
	int b;
};

struct Y:X
{
	int c;
	int d;
};

struct Z:Y
{
	int e;
	int f;
};

void main()
{
		
	system("pause");
	return ;
}

3.5.在堆中建立對象

一、咱們能夠在什麼地方建立對象?
<1>全局變量區
Person P;
<2>棧繼承

void Max()
{
	Person p;
}

<3>堆: new delete
在堆中建立對象:
Person* p= new Person();
釋放對象佔用的內存:
delete p;

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>

class Person
{
private:
	int x;
	int y;

public:
	Person()
	{
		printf("Person()執行了\n");
	}

	Person(int x,int y)
	{
		printf("Person(int x,int y)執行了\n");
		this->x = x;
		this->y = y;
	}

	~Person()
	{
		printf("~Person()執行了\n");
	}
};

void main()
{
	Person* p = new Person(1,2);

	delete p;
	
	system("pause");
	return ;
}

二、new delete的本質:
<1>分析malloc函數的執行流程:
char* p= (char)malloc(128);
<2>分析new的執行流程:
Person
p = new Person);

總結:
new = malloc +構造函數

3.6.引用類型

一、引用就是變量的「別名」

<1>基本類型
intx= 1;
int &p=x;
p=2;					//p就是x
printf("%d \n",x);

<2>類
Person p;
Person &px=p; I
px.x= 10;
printf("%d \n",p.x);

<3>指針
int******i= (int******)1;
int******&r=i;
r= (int******)2;
printf("%d \n",r);

<4>數組
int arr[]={1,2,3};
int (&px)[3] = arr;
px[0]= 100;
//px就是arr
printf("%d \n",arr[0);

二、引用類型與指針的區別

一、引用必須賦初始值,且只能指向一個變量,「從-而終」。
二、對引用賦值,是對其指向的變量賦值,而並非修改引用自己的值。
三、對引用作運算,就是對其指向的變量作運算,而不是對引用自己作運算。
四、引用類型就是一個「弱化了的指針」。

3.7.面向對象之封裝和繼承

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>

class Person
{
private:
	int Age;
	int Sex;
public:
	//父類有參構造函數
	Person(int Age,int Sex)
	{
		this->Age = Age;
		this->Sex = Sex;
	}

	void SetAge(int Age)
	{
		this->Age = Age;
	}
	void SetSex(int Sex)
	{
		this->Sex = Sex;
	}
	void print()
	{
		printf("%d %d\n",Age,Sex);
	}
};

class Teacher:public Person
{
private:
	int Level;

public:
	// :Person(Age,Sex)使用父類的有參構造函數
	Teacher(int Age,int Sex,int Level):Person(Age,Sex)
	{
		this->Level = Level;
	}
	void SetLevel(int Level)
	{
		this->Level = Level;
	}
};

void main()
{
	Teacher t(1,2,3);
	t.print();
	
	system("pause");
	return ;
}

3.8.面向對象之多態

一、純虛函數
<1>虛函數目的是提供-一個統一的接口,被繼承的子類重載,以多態的形式被調用。
<2>若是基類中的函數沒有任何實現的意義,那麼能夠定義成純虛函數:
virtual 返回類型 函數名(參數表)= 0;
<3>含有純虛函數的類被稱爲抽象類(abstract class),不能建立對象。
<4>虛函數能夠被直接使用,也能夠被子類(sub class)重載之後以多態的形式調用,而純虛函數必須在
子類(sub class)中實現該函數纔可使用。

二、什麼是多態?
多態就是可讓父類指針有多種形態。
C++中是經過虛函數實現的多態性。

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>

class Person
{
private:
	int Age;
	int Sex;
public:
	Person(int Age,int Sex)
	{
		this->Age = Age;
		this->Sex = Sex;
	}

	void SetAge(int Age)
	{
		this->Age = Age;
	}
	void SetSex(int Sex)
	{
		this->Sex = Sex;
	}
	//虛函數
	virtual void print()
	{
		printf("%d %d\n",Age,Sex);
	}
};

class Teacher:public Person
{
private:
	int Level;

public:
	Teacher(int Age,int Sex,int Level):Person(Age,Sex)
	{
		this->Level = Level;
	}
	void SetLevel(int Level)
	{
		this->Level = Level;
	}
	//重寫父類的print()
	void print()
	{
		Person::print();
		printf("%d\n",Level);
	}
};

//多態,參數是父類的引用
void MyPrint(Person& p)
{
	p.print();
}

void main()
{
	Teacher t(1,2,3);
	MyPrint(t);
	
	system("pause");
	return ;
}

3.9.運算符重載

Number operator++();
Number operator--0;
Number operator+(const Number& p);
Number operator-(const Number& p);
Number operator*(const Number& p);
Number operator/(const Number& p);
bool operator>(const Number& p);
bool operator<(const Number& p);
bool operator==(const Number& p);
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>

class Number
{
private:
	int x;
	int y;

public:
	Number(int x,int y)
	{
		this->x = x;
		this->y = y;
	}
	//運算符重載
	bool operator>(Number& n)
	{
		return this->x > n.x && this->y > n.y;
	}
};

void main()
{

	Number n1(1,2);
	Number n2(3,4);
	bool r = n1 > n2;
		
	system("pause");
	return ;
}

3.10.模板

一、在函數中使用模版

函數模板的格式:

template <class形參名,dlass 形參名,...>返回類型 函數名(參數列表)
{
	函數體
}
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>

template<class T>
void Sort(T* arr ,int nLength)
{
	int i;
	int k;
	for(i=0;i<nLength-1;i++)
	{
		for(k=0;k<nLength-1-i;k++)
			if(arr[k]> arr[k+1])
			{
				T temp = arr[k];
				arr[k] = arr[k+1];
				arr[k+1] = temp;
			}
	}
};

void main()
{
	int arr[] = {1,3,2,5,4};
	Sort(arr,5);
		
	system("pause");
	return;
}

二、在結構體/類中使用模版
類模板的格式爲:

template<class 形參名,class 形參名,...>class 類名
{
    
}
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>


template<class T,class M>
struct Base
{
	T x;
	T y;

	M a;
	M b;

	int Max()
	{
		if(x>y)
		{
			return x;
		}
		else
		{
			return y;
		}
	}

	char Min()
	{
		if(a<b)
		{
			return a;
		}
		else
		{
			return b;
		}
	}
};

void main()
{
	Base<int,char> base;

	base.x =1;
	base.y =2;
	base.a=3;
	base.b=4;

	int r = base.Max();
		
	system("pause");
	return;
}

3.11.對象拷貝-拷貝構造函數

一、若是不須要深拷貝,不要本身添加拷貝構造函數。

二、若是你添加了拷貝構造函數,那麼編譯器將不在提供,全部的事情都須要由新添加的函數本身來處理:

MyObject(const MyObject& obj) Base(obj)
{
	printf(°拷貝構造函數執行了\n");
	this->x= obj.x;
	this->y= obj.y;
 }

對象拷貝

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>

class CBase
{
private:
	int z;
public:
	CBase(){}
	CBase(int Z)
	{
		this->z = z;
	}
};

class CObfject:public CBase
{
private:
	int x;
	int y;
public:
	CObfject(){}
	CObfject(int x,int y,int z):CBase(z)
	{
		this->x = x;
		this->y = y;
	}
};

void main()
{
	CObfject obj(1,2,3);

	CObfject objNew(obj);

	CObfject* p = new CObfject(obj);
		
	system("pause");
	return;
}

淺拷貝

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>

class CObject
{
private:
	int m_length;
	char* m_strBuffer;
public:
	CObject(){}
	CObject(const char* str)
	{
		m_length = strlen(str) + 1;
		m_strBuffer = new char[m_length];
		memset(m_strBuffer,0,m_length);
		strcpy(m_strBuffer,str);
	}
	~CObject()
	{
		delete[] m_strBuffer;
	}
};

void main()
{
	CObject oldobj("derek");

	CObject newobj(oldobj);  //淺拷貝
		
	system("pause");
	return;
}

深拷貝

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>

class CObject
{
private:
	int m_length;
	char* m_strBuffer;
public:
	CObject(){}
	CObject(const char* str)
	{
		m_length = strlen(str) + 1;
		m_strBuffer = new char[m_length];
		memset(m_strBuffer,0,m_length);
		strcpy(m_strBuffer,str);
	}
    //本身編寫的拷貝構造函數
	CObject(const CObject& obj)
	{
		m_length = obj.m_length;
		m_strBuffer = new char[m_length];
		memset(m_strBuffer,0,m_length);
		strcpy(m_strBuffer,obj.m_strBuffer);
	}
	~CObject()
	{
		delete[] m_strBuffer;
	}
};

void main()
{
	CObject oldobj("derek");

	CObject newobj(oldobj);   //深拷貝
		
	system("pause");
	return;
}

3.12.對象拷貝-重載賦值運算符

一、對象拷貝的兩種形式:
<1>使用拷貝構造函數
<2>使用「=」運算符

二、賦值運算符的問題

賦值運算符「=」與拷貝構造函數-同樣, 都是將成員的值直接複製,都是「淺拷貝」

三、重載賦值運算符:
<1>若是要重重載賦值運算符,必須對全部的屬性都要進行處理。
<2>若是有父類,要顯示調用父類的重載賦值運算符。

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>

class CBase
{
private:
	int m_nLength;
	char* m_pBuffer;
public:
	CBase(){
		m_nLength = 0;
		m_pBuffer = NULL;
	}
	CBase(char* szBuffer)
		{
			this->m_nLength = strlen(szBuffer)+1;
			m_pBuffer = new char[m_nLength];
			strcpy(m_pBuffer,szBuffer);
		}
	CBase& operator=(const CBase& ref)
	{
		m_nLength = ref.m_nLength;
		if(m_pBuffer!=NULL)
			delete[] m_pBuffer;
		m_pBuffer = new char[m_nLength];
		memcpy(m_pBuffer,ref.m_pBuffer,m_nLength);
		return *this;
	}
	virtual ~CBase(){
		delete[] m_pBuffer;
	}
};

void main()
{
	CBase c1("china"),c2("derek");
	c1 = c2;
	
	system("pause");
	return;
}

3.13.static關鍵字

一、面向對象設計中的static之靜態數據成員:
<1>靜態數據成員存儲在全局數據區,且必須初始化,靜態數據成員初始化的格式爲:
<數據類型><類名> :<靜態數據成員名> =<值>
<2>靜態數據成員和普通數據成員同樣聽從public,protected,private訪問規則;
<3>類的靜態數據成員有兩種訪問形式:
<類對象名> <靜態數據成員名>
<類類型名> < 靜態數據成員名>
<4>同全局變量相比,使用靜態數據成員有兩個優點:
避免命名衝突;
能夠實現信息隱藏;

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>

class CBase
{
private:
	int x;
	int y;
	static int z;     //私有的全局變量,CBase類的全部對象公用
public:
	void SetValue(int a)
	{
		z=a;
	}
	int GetValue()
	{
		return z;
	}
};
//靜態成員的初始化
int CBase::z = 0;


void main()
{
	CBase c1,c2;
	c1.SetValue(10);
	int b = c2.GetValue();
	printf("%d\n",b);    //10

	system("pause");
	return;
}
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>

class CBase
{
public:
	CBase(int x,int y);
	static int GetSum();    //靜態成員函數
private:
	int x,y;
	static int Sum;
};

int CBase::Sum = 0;

CBase::CBase(int x,int y)
{
	this->x=x;
	this->y=y;
}
int CBase::GetSum()
{
	return Sum;
}

void main()
{
	CBase::GetSum();

	system("pause");
	return;
}

二、單例模式

一個類只能建立一個對象

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>

class CSingleton
{
public:
	static CSingleton* GetInstance()
	{
		if(m_pInstance == NULL)
			m_pInstance = new CSingleton();
		return m_pInstance;
	}
private:
	CSingleton(){}
	static CSingleton* m_pInstance;    //定義靜態成員
};

CSingleton* CSingleton::m_pInstance = NULL;  //初始化靜態成員


void main()
{
    //兩個實例指向的地址如出一轍
	CSingleton* p1 = CSingleton::GetInstance();  
	CSingleton* p2 = CSingleton::GetInstance();
    
	system("pause");
	return;
}
相關文章
相關標籤/搜索