网站建设 云南,做网站如何更新百度快照,wordpress explode,百度一下百度主页官网目录 一、类 
【1】类 
【2】应用实例 
练习#xff1a; 
【3】封装 
二、this指针 【1】this指针的格式 
【2】必须使用this指针的场合 
三、类中的特殊成员函数 
【1】构造函数 
i#xff09;功能 
ii#xff09;格式 
iii#xff09;构造函数的调用时机 
iv#xff09;…目录 一、类 
【1】类 
【2】应用实例 
练习 
【3】封装 
二、this指针 【1】this指针的格式 
【2】必须使用this指针的场合 
三、类中的特殊成员函数 
【1】构造函数 
i功能 
ii格式 
iii构造函数的调用时机 
iv构造函数允许函数重载 
v构造函数的初始化列表 
1.格式 
2.必须使用初始化列表的情况 
2】析构函数 
i功能 
ii调用时机 
iii格式 
iv需要显性定义出析构函数的情况 
【3】拷贝构造函数 
i功能 
ii格式 
iii调用时机 
iv深浅拷贝问题 
【4】拷贝赋值函数 
i功能 
ii格式 
作业 一、类 面向对象的三大特征封装、继承和多态 C中封装是由类来实现的 C中的类是由结构体演变而来的 结构体变量和函数 类成员属性(变量)、成员方法(函数) 【1】类 
类中成员默认是private权限 
class 类名
{
public:       ----类外和类内都可以访问公有的成员变量/函数
private:      ----类内可以访问类外不能访问私有的成员变量/函数
protected:受保护的成员变量/函数    
}; 
【2】应用实例 
#include iostream
using namespace std;class Person
{
private:string name;
public:int age;int high;void set_name(string n);    //在类内声明函数void show(){cout  name   name   age  age   high  high  endl;}
};int main()
{Person p1;       //实例化一个类对象p1p1.set_name(zhangsan);p1.age  90;p1.high  100;p1.show();return 0;
}//类外实现
void Person::set_name(string n)
{name  n;
} 
练习 1、定义一个矩形类(Rectangle)包含私有成员长(length)、宽(width)定义成员函数 设置长度: void set_len(int l); 设置宽度: void set_wid(int w); 获取长度: int get_len(); 获取宽度: int get_wid(); 显示周长和面积: void show(); #include iostream
using namespace std;class Rec
{int length;int width;
public://所有函数的类内声明void set_len(int l);void set_wid(int w);int get_len();int get_wid();void show();};void Rec::set_len(int l)
{length  l;
}
void Rec::set_wid(int w)
{width  w;
}
int Rec::get_len()
{return length;
}
int Rec::get_wid()
{return width;
}
void Rec::show()
{cout  周长  2*(lengthwidth)  endl;cout  面积  length*width  endl;
}
int main()
{Rec r1;    //实例化了一个Rec类的类对象r1r1.set_len(10);r1.set_wid(3);cout  长:  r1.get_len()  endl;cout  宽:  r1.get_wid()  endl;r1.show();return 0;
} 
【3】封装 把某一事物的所有属性(变量)、行为(成员方法/成员函数)封装成一个整体给私有的属性提供公有的接口以便于用户修改类中成员都有访问权限(public,private,protected)访问权限是对于整个类而言的类中同一访问权限可以可以出现多次类中默认是私有权限 二、this指针 this指针是类内默认提供给非静态成员函数的指针this指向指向类对象本身哪个类对象调用函数this就指向哪一个类对象(谁调用函数this就指向谁) 【1】this指针的格式 
类名 *const this;  -----不能修改指针指向 
【2】必须使用this指针的场合 当成员函数的参数和类中成员属性同名时需要使用this指向表明哪一个是类中的成员属性拷贝赋值函数中需要返回自身的引用也需要使用this指针 #include iostream
using namespace std;class Rec
{int length;int width;
public://所有函数的类内声明void set_len(int length);void set_wid(int width);int get_len();int get_wid();void show();
};void Rec::set_len(int length)
{this-length  length;
}void Rec::set_wid(int width)
{this-width  width;
}int Rec::get_len()
{return length;
}int Rec::get_wid()
{return width;
}void Rec::show()
{cout  周长  2*(lengthwidth)  endl;cout  面积  length*width  endl;
}
int main()
{Rec r1;    //实例化了一个Rec类的类对象r1Rec r2;r2.set_len(20);r1.set_len(10);r1.set_wid(3);cout  长:  r1.get_len()  endl;cout  宽:  r1.get_wid()  endl;r1.show();return 0;
} 
三、类中的特殊成员函数 类中的特殊成员函数程序员如果不手动写出来系统会默认提供 一共有6个特殊的成员函数构造函数、析构函数、拷贝构造函数、拷贝赋值函数取地址运算符的重载和常取地址运算符的重复C11又提供了移动构造、移动赋值函数 本文只有前四个 【1】构造函数 用于实例化类对象系统会自动调用系统自动提供的是无参构造 如果手动定义了构造函数那么系统不会再提供一个无参构造 i功能 
实例化类对象时申请空间使用的 
ii格式 
类名(参数)
{函数体;
} 
iii构造函数的调用时机 栈区什么时候实例化类对象什么时候调用 在 C 中对象可以在栈区实例化这也被称为自动存储类对象。实例化对象时会在栈上为对象分配内存空间并调用对应的构造函数进行初始化。 对象的实例化和调用可以发生在不同的情况下 1.在函数内部当在函数内部定义一个类对象时对象的实例化和构造函数的调用将发生在函数的作用域内。例如 void foo() {MyClass obj;  // 实例化对象并调用构造函数// 函数内的其他操作
} // 函数结束对象超出作用域析构函数将会被调用 2.作为类的成员如果一个类定义在另一个类中并作为成员变量那么对象的实例化和构造函数的调用将随着父类对象的实例化而发生。例如 class ParentClass {
public:MyClass obj;  // 对象作为成员变量
};int main() {ParentClass parentObj;  // 实例化父类对象对象的实例化和构造函数调用都会发生// 其他操作
} // 父类对象超出作用域析构函数将会被调用对象的析构顺序与构造相反 需要注意的是在栈上实例化的对象会在其所在的作用域结束时超出作用域从而自动调用析构函数释放对象占用的内存空间。这种自动释放内存的方式称为自动存储管理。  堆区定义类的指针时不调用构造函数。  什么时候new什么时候调用 应该在对象不再使用时调用对应的析构函数来释放内存以避免内存泄漏。 iv构造函数允许函数重载 系统默认提供一个无参构造函数可以显性定义出有参构造但是此刻系统不再提供默认的无参构造还可以显性写出无参构造构造函数是允许函数重载的 #include iostream
using namespace std;class Stu
{string name;int age;
public://定义Stu类的无参构造Stu(){cout  Stu的无参构造  endl;}//函数重载Stu(string name,int age){this-name  name;this-age  age;cout  Stu的有参构造  endl;}Stu(string name){this-name  name;cout  Stu的对name的有参构造  endl;}
};int main()
{     Stu s1(zhangsan,18);  //栈区的类对象Stu *p;  //在栈区申请一个Stu*类型的指针p  new Stu(lisi);    //在堆区申请一个Stu的空间会调用构造函数return 0;
} v构造函数的初始化列表 
1.格式 
类型(形参):成员属性1(形参1),成员属性2(形参2),······{函数体内容}  构造函数提供了初始化列表的机制可以直接在函数体外执行初始化操作  初始化列表由引出每一个成员属性的值之间以,逗号分隔  2.必须使用初始化列表的情况 形参和成员属性同名类中有引用成员时需要使用初始化列表类中有const修饰的成员时一个类中有另一个类的子对象时需要使用初始化列表(如果两个类都有无参构造是不需要写初始化列表) //包含其他类的子对象
#include iostream
using namespace std;
class Per
{string name;
public://Per提供的有参构造Per(string name){this-name  name;cout  Per的有参构造  endl;}Per(){cout  Per的无参构造  endl;}//一个show函数输出namevoid show(){cout  Per中的name  name  endl;}
};class Stu
{int score;
public:Per p1;    //Stu类中包含另一个类的子对象,且另一个类只有有参构造函数
public:Stu(string name):p1(name)    //必须使用初始化列表并且在初始化列表显性调用另一个类的构造函数{cout  Stu的有参构造  endl;}Stu(){cout  Stu的无参构造  endl;}
};int main()
{Stu s1(zhangsan);//通过s1这个类对象调用Per中的show函数s1.p1.show();Stu s2;return 0;
}//同名或者是包含引用成员/const修饰的成员
class Stu
{string name;//int age;     //类中有引用成员const int score;
public://定义Stu类的无参构造
//    Stu()
//    {
//        cout  Stu的无参构造  endl;
//    }//函数重载使用初始化列表的方式//初始化列表也可以解决形参和成员属性同名问题Stu(string name,int age):name(name),score(age)  //在函数体外给成员属性初始化{cout  Stu的有参构造  endl;}void show(){cout  name     score  endl;}
};int main()
{     Stu s1(zhangsan,18);  //栈区的类对象s1.show();Stu *p;  //在栈区申请一个Stu*类型的指针p  new Stu(lisi,20);    //在堆区申请一个Stu的空间会调用构造函数return 0;
} 
2】析构函数 析构函数不支持函数重载并且析构函数只有~类名(){} 不需要传参数public权限 i功能 
回收类对象的空间 
ii调用时机 栈区类对象消亡时自动调用 堆区什么时候delete什么时候调用析构函数 先构造的后析构后构造的先析构 iii格式 
~类名()
{函数体;
} 
iv需要显性定义出析构函数的情况 类中有指针成员并且指针成员指向堆区的空间如果直接调用普通的析构函数类对象消亡后没有办法再去释放掉堆区的空间会造成内存泄漏 #include iostream
using namespace std;class Stu
{int *p;
public:Stu():p(new int)    //在不传参的情况下给指针成员p用堆区的空间初始化{cout  Stu无参构造  endl;}Stu(int a):p(new int(a))   //在参数为整形变量的情况下让p指向堆区申请的空间//但是把这篇空间的内容用传过来的整形变量初始化{cout  Stu的有参构造  endl;}Stu(int *p)   //要求传过来的指针的值一定是指向堆区空间{this-p  p;cout  Stu传指针的有参构造  endl;}~Stu(){//在析构之前释放堆区的空间cout  准备释放空间  p  endl;delete p;p  nullptr;cout  Stu的析构函数  endl;}
};int main()
{Stu s1(90);return 0;
} 
【3】拷贝构造函数 
i功能 
使用已有的类对象给类对象初始化的时候自动调用拷贝构造函数 
ii格式 
类名(类名 other)
{函数体的内容;
}拷贝构造函数是一个构造函数
函数名:类名
形参:其他类对象的引用 
iii调用时机 使用已有的类对象给新的类对象初始化当函数的形参是一个类对象时也会调用拷贝构造函数当函数的返回值是一个类对象时也会调用拷贝构造函数 #include iostream
using namespace std;
class Stu
{string name;
public:Stu(){cout  Stu的无参构造  endl;}Stu(string name){this-name  name;cout  Stu的有参构造  endl;}Stu(Stu other)   //Stu的拷贝构造函数和无参构造以及有参构造构成函数冲澡{this-name  other.name;cout  Stu的拷贝构造函数  endl;}void show(){cout  name  endl;}
};
Stu fun(Stu s1)  //定义了一个函数fun形参是一个类对象
{cout  调用成功  endl;return s1;
}
int main()
{Stu s1(zhangsan);cout  s1;s1.show();Stu s2  s1;   //拷贝构造函数cout  s2;s2.show();fun(s2);return 0;
} iv深浅拷贝问题 什么情况下发生类中存在指针成员时 深拷贝两个指针成员指向不同空间但是取*的结果是一致 浅拷贝两个指针成员指向同一片空间 1、对同一片空间二次释放问题 2、两个类对象使用同一片空间发生资源抢占问题 #include iostream
using namespace std;class Stu
{int *p;
public:Stu():p(new int)    //在不传参的情况下给指针成员p用堆区的空间初始化{cout  Stu无参构造  endl;}Stu(int a):p(new int(a))   //在参数为整形变量的情况下让p指向堆区申请的空间//但是把这篇空间的内容用传过来的整形变量初始化{cout  Stu的有参构造  endl;}Stu(int *p)   //要求传过来的指针的值一定是指向堆区空间{this-p  p;cout  Stu传指针的有参构造  endl;}~Stu(){//在析构之前释放堆区的空间cout  准备释放空间  p  endl;delete p;p  nullptr;cout  Stu的析构函数  endl;}void show(){cout  p  p  endl;}void set_p(int a){*p  a;    //通过指针变量p修改内存中的值}void show_p(){cout  *p  endl;  //通过指针变量输出p指向的内存中的值}//拷贝构造函数Stu(Stu other){p  new int;  //手动让s2的指针p指向堆区的空间//实现深拷贝*p  *(other.p);cout  Stu的拷贝构造函数  endl;}
};
int main()
{Stu s1(90);    //会给s1的指针成员在堆区申请一片空间使用90初始化Stu s2  s1;   //申请了一个Stu的类对象的空间也实现了用s1的值初始化s2//左调右参//上面一行调用了拷贝构造函数//使用了默认提供的拷贝构造会造成指针成员指向同一片空间的问题
//    cout  s1:;
//    s1.show();
//    cout  s2:;
//    s2.show();s1.show_p();s2.show_p();s1.set_p(101);s1.show_p();s2.show_p();return 0;
} 【4】拷贝赋值函数 
i功能 
使用已有的类对象给已有的类对象赋值的时候会调用拷贝赋值函数。 
ii格式 
类名 operator(const 类名 other)
{函数体;
} 
作业 设计一个Per类类中包含私有成员姓名、年龄、指针成员身高、体重再设计一个Stu类类中包含私有成员成绩、Per类对象 p1设计这两个类的构造函数、析构函数和拷贝构造函数。 #include iostreamusing namespace std;class Per{string name;int age;float* height;float* weight;
public://构造函数Per(string name,int age,float* height,float* weight){this-name  name;this-age  age;this-height  height;this-weight  weight;cout  Per的构造函数  endl;}//析构函数~Per(){delete height;delete weight;height  nullptr;weight  nullptr;cout  Per的析构函数  endl;}//拷贝构造函数Per(Per other){this-name  other.name;this-age  other.age;height  new float;*height  *(other.height);weight  new float;*weight  *(other.weight);cout  Per的拷贝构造函数  endl;}void show(){cout  name  endl;}
};class Stu{float score;Per p1;
public://必须使用初始化列表的情况//形参和成员属性同名//类中有引用成员时需要使用初始化列表//类中有const修饰的成员时//一个类中有另一个类的子对象时需要使用初始化列表(如果两个类都有无参构造是不需要写初始化列表)//Stu构造函数Stu(float score,string name,int age,float* height,float* weight):score(score),p1(name,age,height,weight){cout Stu的构造函数  endl;}//析构函数~Stu(){   cout  Stu的析构函数  endl;}//拷贝构造函数Stu(Stu other):score(other.score),p1(other.p1){cout  Stu的拷贝构造函数  endl;}
};int main()
{float height  175;float weight  60;Per p(zhangsan,18,height,weight);Per p1  p;Stu stu1(85.5,lisi,18,height,weight);Stu stu2  stu1;p.show();return 0;
}