一、new和delete 堆区空间操作
1、new和delete操作基本类型的空间
new与C语言中malloc、delete和C语言中free 作用基本相同
区别:
new 不用强制类型转换
new在申请空间的时候可以 初始化空间内容
2、 new申请基本类型的数组
3、new和delete操作类的空间
4、new申请操作对象数组
二、静态成员
1、概念
类的对象 拥有独立的 普通成员数据。
static 修饰的成员 叫 静态成员。
class Data
{int a;//普通成员数据static int a;//静态成员数据static void func()//静态成员函数
{
}
};
2、静态成员数据
static修饰的静态成员 属于类而不是对象(所有对象 共享 一份 静态成员数据)。
实战案例:使用静态成员数据 统计对象的个数
#pragma warning(disable:4996)
#include<iostream>
using namespace std;
class Data
{
public:int mA;//普通成员数据static int count;//静态成员数据
public:Data(){count++;}Data(int a){mA = a;count++;}Data(const Data &ob){count++;}~Data(){count--;}
};
//类外初始化
int Data::count = 0;
void test()
{Data ob1;Data ob2(10);Data ob3 = ob2;cout << "对象个数:" << Data::count << endl;//3{Data ob4;Data ob5;cout << "对象个数:" << Data::count << endl;//5}cout << "对象个数:" << Data::count << endl;//3
}
int main(int argc, char* argv[])
{test();return 0;}
3、静态成员函数
静态成员函数直接通过类名称访问
静态成员函数内 只能操作静态成员数据,因为普通成员数据还没有空间。
三、单例模式
单例模式可以保证结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。即单例模式的类 只能实例化 一个对象。
核心:将构造函数私有化
#include <iostream>
using namespace std;
class SingleTon//单例模式
{
//构造私有化 防止实例化其他对象
private:SingleTon(){count=0;cout<<"构造"<<endl;}SingleTon(const SingleTon &ob){count=0;}~SingleTon(){cout<<"析够"<<endl;}
private://const防止p 在类内部 被修改指向static SingleTon * const p;//保存唯一的实例地址int count;//统计任务执行次数public:static SingleTon * getSingleTon(void)//获取唯一的实例地址{return p;}//用户自定义 任务函数void printString(char *str){count++;cout<<"当前第"<<count<<"次任务打印:"<<str<<endl;}
};
SingleTon *const SingleTon::p = new SingleTon;//创建唯一的实例int main(int argc, char *argv[])
{//获取单例的地址SingleTon *p1 =SingleTon::getSingleTon();//执行任务p1‐>printString("学历证明1");p1‐>printString("身份证明1");SingleTon *p2 =SingleTon::getSingleTon();p2‐>printString("学历证明2");p2‐>printString("身份证明2");
}
四、类的存储结构
成员函数、静态成员 是独立存储 是所有对象共享,不占类的空间。
五、this指针
this是一个隐藏的指针,可以在类的成员函数中使用,它可以用来指向调用对象。当一个对象的成员函数被调用时,编译器会隐式地传递该对象的地址作为 this 指针。
this 指针是一个特殊的指针,它指向当前对象的实例。每一个对象都能通过 this 指针来访问自己的地址。
this可以完成链式操作
六、const修饰成员函数
const 修饰成员函数为只读(该成员函数不允许对 成员数据 赋值) mutable修饰的成员除外。
七、友元
预知识:类将数据和方法封装在一起 加以权限区分 用户只能通过公共方法 操作私有数据。(封装 性)
定义:一个函数或者类 作为了另一个类的友元 那么这个函数或类 就可以直接访问 另一个类的私 有数据。应用:友元 主要用在运算符重载上
友元语法:friend关键字只出现在声明处,其他类、类成员函数、全局函数都可声明为友元,友元函数不是类的成员,不带 this指针友元函数可访问对象任意成员属性,包括私有属性。
现实生活中也可以很好地理解:比如你的家,有客厅,有你的卧室,那么你的客厅是Public的,所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你能进去,但是呢,你也可以允许你的闺蜜好基友进去。程序员可以把一个全局函数、某个类中的成员函数、甚至整个类声明为友元。
1、普通全局函数 作为类的友元
2、 类的某个成员函数 作为另一个类的友元
#pragma warning(disable:4996)
#include<iostream>
#include <string>
using namespace std;
class room;//向前声明,只能说明类名称
class Frind
{
public:void visiting01(Room& room);void visiting02(Room& room);
};
class Room
{friend void goodGay::visiting02(Room &room);
private:string bedroom;//实例化对象
public:string livingroom;
public:Room(string bedroom,string livingroom){this-> bedroom = bedroom;this-> livingroom = livingroom;}
};
void test()
{Room room("我的卧室", "我的客厅");Frind ob;ob.visiting01(room);ob.visiting02(room);
}
int main(int argc, char* argv[])
{test();return 0;}void Frind::visiting01(Room& room)
{cout << "李四访问到" << room.livingroom << endl;//cout<<"李四访问到"<<room.bedRoom<<endl;该成员函数不是类的友元,报错
}void Frind::visiting02(Room& room)
{cout << "好基友张三访问到" << room.livingroom << endl;cout << "好基友张三访问到" << room.bedroom << endl;}
3、整个类作为 另一个类的友元
这个类的所有成员函数 都可以访问另一个类的私有数据
#pragma warning(disable:4996)
#include<iostream>
#include <string>
using namespace std;
class room;//向前声明,只能说明类名称
class Frind
{
public:void visiting01(Room& room);void visiting02(Room& room);
};
class Room
{friend class Frind;
private:string bedroom;//实例化对象
public:string livingroom;
public:Room(string bedroom,string livingroom){this-> bedroom = bedroom;this-> livingroom = livingroom;}
};
void test()
{Room room("我的卧室", "我的客厅");Frind ob;ob.visiting01(room);ob.visiting02(room);
}
int main(int argc, char* argv[])
{test();return 0;}void Frind::visiting01(Room& room)
{cout << "李四访问到" << room.livingroom << endl;cout<<"李四访问到"<<room.bedRoom<<endl;
}void Frind::visiting02(Room& room)
{cout << "好基友张三访问到" << room.livingroom << endl;cout << "好基友张三访问到" << room.bedroom << endl;}
4、案例
(1)遥控器的类
#include <iostream>
using namespace std;
class TV;
class Remote//遥控器类
{
private:TV *p;
public:Remote(TV *p);void offOrOn(void);//开关void upVolume(void);//音量void downVolume(void);void upChannel(void);//频道void downChannel(void);void showTv(void);void setChannel(int channel);
};
class TV
{friend void Remote::setChannel(int channel);enum{OFF, ON};enum{minVol, maxVol=10};enum{minChan, maxChan=25};
private:int state;int volume;int channel;
public:TV(){state = OFF;volume = minVol;channel = minChan;}void offOrOn(void);void upVolume(void);void downVolume(void);void upChannel(void);void downChannel(void);void showTv(void);};
int main(int argc, char *argv[])
{//实例化一个电视机TV tv;Remote re(&tv);re.offOrOn();re.upVolume();re.upVolume();re.upVolume();re.setChannel(20);re.showTv();return 0;
}
void TV::offOrOn()
{state = (state==OFF?ON:OFF);return;
}
void TV::upVolume()
{if(volume == maxVol){cout<<"音量已经最大了"<<endl;return;
}volume++;return;
}void TV::downVolume()
{if(volume == minVol){cout<<"音量已经最小了"<<endl;return;
}volume‐‐;return;
}
void TV::upChannel()
{if(channel == maxChan){cout<<"频道已经最大了"<<endl;return;}channel++;return;
}void TV::downChannel()
{if(channel == minChan){cout<<"频道已经最小了"<<endl;return;}channel‐‐;return;
}
void TV::showTv()
{cout<<"当前电视机的状态:"<<(state==OFF?"关":"开")<<endl;cout<<"当前电视机的音量:"<<volume<<endl;cout<<"当前电视机的频道:"<<channel<<endl;
}
Remote::Remote(TV *p)
{this‐>p = p;
}
void Remote::offOrOn()
{p‐>offOrOn();
}void Remote::upVolume()
{p‐>upVolume();
}
void Remote::downVolume()
{p‐>downVolume();
}void Remote::upChannel()
{p‐>upChannel();
}void Remote::downChannel()
{p‐>downChannel();
}void Remote::showTv()
{p‐>showTv();
}
void Remote::setChannel(int channel)
{p‐>channel = channel;
}
(2)动态数组类
根据数据大小动态增减空间。
array.h
#ifndef ARRAY_H
#define ARRAY_H
class Array
{
private:int *arr;//存放首元素地址int capacity;//容量int size;//大小
public:Array();Array(int capacity);Array(const Array &ob);~Array();int getCapacity() const;int getSize() const;void printArray(void);//插入尾部元素void pushBack(int elem);//删除尾部元素void popBack(void);int &at(int pos);
};#endif // ARRAY_H
array.cpp
#include "array.h"
#include<string.h>
#include<iostream>
using namespace std;
int Array::getCapacity() const
{return capacity;
}int Array::getSize() const
{return size;
}void Array::printArray()
{int i=0;for(i=0;i<size; i++){cout<<arr[i]<<" ";}cout<<endl;return;
}void Array::pushBack(int elem)
{//判断容器是否满if(size == capacity){//申请空间int *tmp = new int[2*capacity];//将就空间的内容 拷贝到新空间memcpy(tmp, arr, capacity*sizeof(int));//释放原有的空间delete [] arr;//更新arr的空间arr = tmp;//更新容量capacity = 2*capacity;}arr[size]=elem;size++;return;
}
void Array::popBack()
{if(size == 0){cout<<"容量为空"<<endl;} else{size‐‐;}return;
}
int& Array::at(int pos)
{if(pos<0 || pos >=size){cout<<"访问违法内存"<<endl;exit(‐1);}return arr[pos];
}
Array::Array()
{capacity = 5;size = 0;arr = new int[capacity];//空间清0memset(arr, 0, sizeof(int)*capacity);
}
Array::Array(int capacity)
{this‐>capacity = capacity;size = 0;arr = new int[capacity];//空间清0memset(arr, 0, sizeof(int)*capacity);
}
Array::Array(const Array &ob)
{capacity = ob.capacity;size = ob.size;//深拷贝arr = new int[capacity];memcpy(arr, ob.arr, sizeof(int)*capacity);
}
Array::~Array()
{if(arr != NULL){delete [] arr;arr = NULL;}
}
main.c
#include <iostream>
#include "array.h"
using namespace std;
int main(int argc, char *argv[])
{Array ob;cout<<ob.getCapacity()<<" "<<ob.getSize()<<endl;ob.pushBack(10);ob.pushBack(20);ob.pushBack(30);ob.pushBack(40);ob.printArray();cout<<ob.getCapacity()<<" "<<ob.getSize()<<endl;ob.pushBack(50);ob.pushBack(60);ob.printArray();cout<<ob.getCapacity()<<" "<<ob.getSize()<<endl;ob.popBack();ob.popBack();ob.printArray();cout<<ob.getCapacity()<<" "<<ob.getSize()<<endl;cout<<"arr[2] = "<<ob.at(2)<<endl;ob.at(2) = 100;ob.printArray();return 0;
}