类和对象
类:一些具有共同特征的事物的抽象
属性:(数据成员) 行为(操作,函数:成员函数)
对象:类的具体化
基本语法:
class MM 关键字class
{
public:}1.权限限定词 :限定类外对象对数据成员的访问
1.1 限定对象的访问权限
1.2 类外只能访问public:公有 公有接口
1.3 protected:保护+private:私有
2.构造函数
3.析构函数
4.拷贝构造函数(深拷贝和浅拷贝)
#include<iostream>#include<string>
using namespace std;
class MM
{//默认为私有int age;
public:
string name;//公有接口:类外法无法直接访问age num money ,通过类中添加公有接口函数voidinitData(string sName,int sAge,int sNum,int sMoney){
name = sName;
age = sAge;
num = sNum;
money = sMoney;}voidprint(){
cout << name <<":"<< age <<":"<< num <<":"<< money << endl;}
protected:int num;voidprintInfo(){}
private:int money;};struct boy
{//默认为公有
protected: C++中的结构体允许存在权限限定词
};intmain(){
MM myMM;
myMM.name ="小可爱";//myMM.age=14; age不能被类外对象对自己访问 类中可以
myMM.initData("小可爱",19,1001,1000000);
myMM.print();return0;}
二、基本构造函数
构造函数: 对象创建时候初始化
1.名字和类名相同
2.没有返回值
3.不需要自己调用,构造对象的时候被调用
4.对象长相是由构造函数决定
5.不写构造函数就存在默认的(无参)构造函数
一旦写了构造函数,默认的不存在
一般情况默认的构造函数是公有类型
#include<iostream>#include<string>
using namespace std;
class X
{
public://是因为存在一个默认的构造函数,可以构造无参对象//X() = delete;};
class MM
{
public:MM(){ name =""; age =0;};MM(string sName,int sAge)//写了默认的就不存在{
name = sName;
age = sAge;}voidprint(){
cout << name <<":"<< age << endl;}
protected://一般数据写保护类型
string name;int age;};intmain(){
X xObject;
MM mm("mm",18);//MM mm;错误 创建对象必要与构造函数参数一样
MM* p = new MM("小可爱",45);//无名对象:也创建对象 也调用构造函数
MM array[4];//函数重载无参构造函数 可以用来构造数组 数组:无参的对象
delete p;
p = nullptr;return0;}
三、拷贝构造函数
拷贝构造函数 还可以二次初始化多次初始化
1.拷贝构造函数也是一个构造函数
特点:只有一个参数:对对象引用
2.也存在一个默认的构造函数
3.赋值的时候会调用拷贝构造函数
4.作用:实现对象与对象之间的赋值
#include<iostream>#include<string>
using namespace std;
class MM
{
public:MM(string sName,int sAge)//公有接口{
name = sName;
age = sAge;}//拷贝构造函数//MM(const MM& object) 其他地方用const修饰 也是拷贝构造函数MM(MM& object){
name = object.name;//实现赋值操作
age = object.age;
cout <<"调用自己的拷贝构造函数"<< endl;//自己写的拷贝构造函数 }voidprint(){
cout << name <<"\t"<< age << endl;}
protected:
string name;int age;};voidprintMM(MM object)//MM object=myMM 创建了新的对象 传参就是赋值过程 调用拷贝构造函数{
object.print();}voidprintMM2(MM& object)//实参的别名,没有产生新的对象 不会调用拷贝构造函数{
object.print();}
class boy
{
public:boy(string sName,int sAge){
name = sName;}
string name;int age;};intmain(){
MM yourMM("天狗",18);//1.赋值的时候被调用
MM myMM = yourMM;//调用默认的拷贝构造函数
myMM.print();//2.构造对象的时候被调用
MM mm(myMM);
mm.print();//3.函数传参:赋值过程 引用类型不会调用拷贝构造函数printMM(myMM);printMM2(myMM);//测试
boy myBoy("夜舞",18);
boy yourBoy(myBoy);//存在默认拷贝构造函数return0;}
四、析构函数
析构函数:
1.析构函数用来释放对象中的属性申请的内存
对象的属性做了动态内存申请,需要手动写析构函数
2.不写析构函数存在默认的析构函数
3.函数名:~类名 参数:无参 无法被重载
构造函数可以被重载,因为构造函数可以有多个且可以带参数。
析构函数不可以被重载,因为析构函数只能有一个,且不能带参数。
4.对象死亡的时候被调用:作用域结束 不是main函数结束 生命周期结束
5.析构是公有类型
#include<iostream>#include<string>
using namespace std;//析构函数调用的时候
class MM
{
public:~MM(){
cout <<"析构函数"<< endl;//墓志铭}
protected:};//类中的属性申请了内存
class student
{
public:student(constchar* str,int sAge)//构造函数{
name = new char[strlen(str)+10];strcpy(name, str);
age = sAge;}voidprint(){
cout << name <<":"<< age << endl;}~student(){
delete[]name;
cout <<"释放成功"<< endl;}
protected:char* name;int age;};intmain(){{//作用域分辨符 提前结束生命周期
MM mm;
MM* p = new MM;//动态内存申请的需要手动释放
delete p;
p = nullptr;//收尾工作}//手写:{
student myStudent("yykkk",18);
myStudent.print();}return0;}
五、深浅拷贝
默认的拷贝都是浅拷贝
浅拷贝:没有申请内存情况下
浅拷贝释放时导致释放失败 两个指针指向同一个位置
两个位置重复被释放导致析构问题
#include<iostream>#include<string.h>#include<string>
using namespace std;
class MM
{
public:MM(constchar* str){
name = new char[strlen(str)+1];strcpy(name, str);}MM(MM& object){//name = object.name;
name = new char[strlen(object.name)+1];strcpy(name, object.name);}~MM(){
delete[] name;}
protected:char* name;//习惯于数据成员写成protected};intmain(){{
MM mm("小仙女");
MM myMM = mm;}
string str ="Iloveyou";//赋值 拷贝构造函数
string str1(str);//创建新对象 调用拷贝构造函数return0;}
六、this指针
this:代表每一个对象的首地址 //*this 对象本身
可以避免形参名字和数据成员名字相同的问题
用来区别
#include<iostream>#include<string>
using namespace std;
class MM
{
public:MM(string name,int age){
this->name = name;//this->age = age; (*this).age = age;//*this 对象本身}voidprint(){
cout << this->age <<":"<< age << endl;}//返回对象本身
MM&returnObject()//MM returnObject(){return*this;}
protected:
string name;int age;};intmain(){
MM mm("张三",18);//无实际作用
mm.returnObject().returnObject().returnObject().returnObject().returnObject().print();
MM yourMM("里斯",29);
yourMM.returnObject().print();return0;}
七、构造顺序与析构顺序
1.构造函数顺序和构造顺序相反
2.delete可以直接调用析构函数
3.静态变量是最后调用析构函数 程序运行之前分配内存
函数传参 隐藏的赋值操作
#include<iostream>#include<string>
using namespace std;
class A
{
public:A()//构造函数{
cout <<"A";}//存在默认的拷贝构造函数voidprint(){
cout <<"B";}~A()//析构函数没有参数不能重载{
cout <<"C";}};voidprint(A a)//A a=实参 //存在临时对象 调用默认的拷贝构造函数{
a.print();//B C}intmain(){{//预符号:提早把对象干掉 vs2013//1.正常情况构造顺序和析构顺序相反
A a;//Aprint(a);//BC!!
A array[3];//AAA CCC C }
cout << endl;{//new出来,什么时候delete 什么时候调用析构函数
A a;//A
A* p = new A;//A //手动写的手动delete
delete p;
p = nullptr;//C
A b;//A C C}
cout << endl;{
A a;//A
A* p = new A;//A
A b;//A CC}
cout << endl;{static A static_A;}return0;}