返回顶部
扩大
缩小

Zhang_derek

逆向初级-C++(三)

3.1.封装

1、什么是封装:
将函数定义到结构体内部,就是封装。
2、什么是类:
带有函数的结构体,称为类。
3、什么是成员函数:
结构体里面的函数,称为成员函数。

#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指针

1、什么是this指针

1、this指针是编译器默认传入的,通常都会使用ecx进行参数的传递。
2、你用或者不用,它都在那。

3、this指针不能做++-等运算,不能重新被赋值。
4、this指针不占用结构体的宽度。

2、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.构造函数与析构函数

1、构造函数

1、与类同名,没有返回值
2、创建对象的时候执行,主要用于初始化
3、可以有多个(最好有一个无参的),称为重载,其他函数也可以重载
4、编译器不要求必须提供

2、析构函数总结:
1、只能有一个析构函数不能重载
2、不能带任何参数
3、不能带返回值
4、主要用于清理工作
5、编译器不要求必须提供

#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.继承

1、什么是继承?
继承就是数据的复制
2、为什么要用继承?
减少重复代码的编写

#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、我们可以在什么地方创建对象?
<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 ;
} 

2、new delete的本质:
<1>分析malloc函数的执行流程:
char* p= (char)malloc(128);
<2>分析new的执行流程:
Person
p = new Person);

总结:
new = malloc +构造函数

3.6.引用类型

1、引用就是变量的“别名”

<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);

2、引用类型与指针的区别

1、引用必须赋初始值,且只能指向一个变量,“从-而终”。
2、对引用赋值,是对其指向的变量赋值,而并不是修改引用本身的值。
3、对引用做运算,就是对其指向的变量做运算,而不是对引用本身做运算。
4、引用类型就是一个“弱化了的指针”。

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、纯虚函数
<1>虚函数目的是提供-一个统一的接口,被继承的子类重载,以多态的形式被调用。
<2>如果基类中的函数没有任何实现的意义,那么可以定义成纯虚函数:
virtual 返回类型 函数名(参数表)= 0;
<3>含有纯虚函数的类被称为抽象类(abstract class),不能创建对象。
<4>虚函数可以被直接使用,也可以被子类(sub class)重载以后以多态的形式调用,而纯虚函数必须在
子类(sub class)中实现该函数才可以使用。

2、什么是多态?
多态就是可以让父类指针有多种形态。
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.模板

1、在函数中使用模版

函数模板的格式:

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;
} 

2、在结构体/类中使用模版
类模板的格式为:

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.对象拷贝-拷贝构造函数

1、如果不需要深拷贝,不要自己添加拷贝构造函数。

2、如果你添加了拷贝构造函数,那么编译器将不在提供,所有的事情都需要由新添加的函数自己来处理:

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、对象拷贝的两种形式:
<1>使用拷贝构造函数
<2>使用“=”运算符

2、赋值运算符的问题

赋值运算符“=”与拷贝构造函数-一样, 都是将成员的值直接复制,都是“浅拷贝”

3、重载赋值运算符:
<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关键字

1、面向对象设计中的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;
} 

2、单例模式

一个类只能创建一个对象

#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;
} 
作者:zhang_derek

个性签名:其实人跟树一样,越是向往高处的阳光,它的根就越要伸向黑暗的地底。

posted on 2021-04-09 12:29  zhang_derek  阅读(74)  评论(0编辑  收藏  举报

导航