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