• 逆向初级-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("没有参数的构造函数
    ");
    	}
    
    	Student(int a,int b,int c)
    	{
    		this->a = a;
    		this->b = b;
    		this->c = c;
    		printf("有参数的构造函数
    ");
    	}
    
    	~Student()
    	{
    		printf("析造函数
    ");	
    	}
    
    	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()执行了
    ");
    	}
    
    	Person(int x,int y)
    	{
    		printf("Person(int x,int y)执行了
    ");
    		this->x = x;
    		this->y = y;
    	}
    
    	~Person()
    	{
    		printf("~Person()执行了
    ");
    	}
    };
    
    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 
    ",x);
    
    <2>类
    Person p;
    Person &px=p; I
    px.x= 10;
    printf("%d 
    ",p.x);
    
    <3>指针
    int******i= (int******)1;
    int******&r=i;
    r= (int******)2;
    printf("%d 
    ",r);
    
    <4>数组
    int arr[]={1,2,3};
    int (&px)[3] = arr;
    px[0]= 100;
    //px就是arr
    printf("%d 
    ",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
    ",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
    ",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
    ",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(°拷贝构造函数执行了
    ");
    	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
    ",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

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

  • 相关阅读:
    Python合集之Python循环语句(二)
    io流2
    io流
    集合工具类
    泛型
    Map
    VSCode_Extensions
    C++ in VSCode
    C# 私有字段前缀 _ 的设置(VS2019, .editorconfig)
    dotnet 跨平台编译发布
  • 原文地址:https://www.cnblogs.com/derek1184405959/p/14636611.html
Copyright © 2020-2023  润新知