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 ; }
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); } };
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 ; }
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 ; }
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 +构造函数
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、引用类型就是一个“弱化了的指针”。
#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 ; }
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 ; }
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 ; }
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; }
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; }
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; }
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; }