类的相关内容:

基础知识 :

 //面向对象的三大特性: 封装,继承,多态
//首先是封装:  语法:  class 类名 {访问权限:  属性/行为 };

案例:设计一个圆类,计算它的周长

#include
using namespace std;const double pi = 3.14;
class circle
{
public :void change(int x);void show();private:int r;
};
void circle::change(int x)
{r = x;
}
void circle::show()
{cout << "圆的周长为:" << 2 * pi * r << endl;
}
int main()
{circle c1;//使用类时,必须要实例化一个对象出来,不然不能访问其属性和行为int r=0;cout << "请输入您要计算的圆的半径:" << endl;cin >> r;c1.change(r);c1.show();
}

案例2:设计一个学生类,属性有姓名和学号,
可以给姓名和学号赋值,可以显示学生的姓名和学号

#include 
using namespace std;
#include
class Student 
{
private:string s_name;string s_number;
public:void changestudent(string , string );void show();
};
void Student ::changestudent(string name, string number)
{s_name = name;s_number = number;}
void Student::show()
{cout << "姓名为:" << s_name << endl;cout << "学号为:" << s_number << endl;
}
int main()
{Student s;string name;string number;cout << "请输入学生姓名:" << endl;cin >> name;cout << "请输入学生学号:" << endl;cin >> number;s.changestudent(name,number);cout << "录入完毕!请查看" << endl;s.show();
}

 struct  和 class 的区别:

struct 默认权限为公有   class 默认权限为私有
成员属性设置为私有的好处:
①(控制权限)将左右成员属性设置为私有,可以自己控制读写权限:
可以通过 public: 中添加行为(函数),
来作为桥梁控制私有属性和行为  :可以返回 ,写入  操作
②  设置范围,避免犯错 :
比如:
void setage (int age)   //设计年龄写入的范围
{
if(age <0 || age >150)
{
cout << "您输入有误,请重新输入"< m_age = 0;
return;
}
//否则赋值:
m_age = age;
}

案例①

设计立方体类(cube)
求出立方体的面积和体积
分别用全局函数和成员函数判断两个立方体是否相等

#include
using namespace std;class Cube
{
public://求出面积void area();//求出体积double volume();void change(double, double, double);int fanH(){return m_h;}int fanl(){return m_l;}int fanW(){return m_w;}//用成员函数判断两个立方体相不相等:void func3(Cube s1,Cube s2){if (s1.m_h   == s2.m_h  && s1.m_l  == s2.m_l  && s1.m_w  == s2.m_w ){cout << "从成员函数中判断:两个立方体相等!" << endl;}elsecout << "从成员函数中判断:两个立方体不相等!" << endl;}
private:double m_h;double m_l;double m_w;
};
void Cube::change(double h, double l, double w)
{m_h = h; //高m_l = l;  //长m_w = w;  //宽
}
double Cube::volume() //定义求体积的函数
{double  V = m_h * m_l * m_w;cout << "体积为:" << V << endl;return V;
}
void Cube::area() //定义求体积的函数
{double area = (m_h *m_w* 2) + (m_l * m_w* 2) + (m_l* m_h * 2);cout << "面积为:" << area << endl;
}
//用全局函数判断两个立方体是否相等:长宽高必须分别相等
//  因为全局函数中无法调用 私有成员  所以必须要从类中返回长宽高
void func(double h1,double i1,double w1,double h2,double i2,double w2)
{if (h1==h2 &&i1==i2 && w1 ==w2){cout << "两个立方体相等!" << endl;}elsecout << "两个立方体不相等!" << endl;
}int main()
{Cube s1,s2;cout << "第一个立方体:" << endl;s1.change(5.1, 8.7,9.1);s1.area();s1.volume();cout << "第二个立方体:" << endl;s2.change(5.6, 8.4, 8.58);s2.area();s2.volume();//从类中返回长宽高int h1 = s1.fanH();int i1 = s1.fanl();int w1 = s1.fanW();int h2 = s2.fanH();int i2 = s2.fanl();int w2 = s2.fanW();//判断是否相等func(h1, i1, w1, h2, i2, w2);s1.func3(s1,s2);
}

案例2 : 

自己敲的版本:  圆形固定在了(0,0)点 不灵活

#include
using namespace std;
#include class circle
{
public://声明一个计算两点之间距离的公式:void sumD(double c_x, double c_y,double r);double countD();double fanr(){return c_r;}
private:double c_x; //点的坐标x值double c_y; //点的坐标y值double c_r; //圆的半径
};
void circle::sumD(double x,double y,double r)
{c_x = x;c_y = y;c_r = r;
}
double  circle::countD()
{int d = sqrt(pow(c_x, 2) + pow(c_y, 2));return d;
}
int main()
{circle s;s.sumD(5.6, 9.2, 8.4);double d = s.countD();double r = s.fanr();if (d == r){cout << "点在圆上" << endl;}else if (d > r){cout << "点在圆外" << endl;}else if (d < r){cout << "点在圆内" << endl;}
}

提高版本:圆心也是任意的, 传入和调用参数的时候 用到引用

 构造函数 和 析构函数 :

对象的初始化和清理也是两个非常重要的安全问题:

①一个对象或者变量没有初始化状态,对其使用后果也是未知的

②同样的使用完一个对象或者变量,没有及时清理,也会造成一定的安全问题

解决

c++中用构造函数和析构函数解决以上问题,这两个函数会被编译器自动调用

,如果我们不提供构造和析构,编译器会提供空实现的(构造和析构函数)。

构造函数: 

主要作用在于创建对象时为对象的成员属性赋值,由编译器自动调用(无需手动)

构造函数语法: 

  1. 类名(){ }
  2. 没有返回值也不写void 
  3. 构造函数可以有参数,因此可以发生重载 
  4. 无需手动调用 ,而且只会调用一次。

析构函数:

主要作用于在对象销毁前系统自动调用,执行一些清理工作。

析构函数语法:

  1. ~ 类名 (){ } 
  2. 析构函数也不用写返回值  ,也不写void 
  3. 函数名称与类名相同,在名称前加上符号~ 
  4. 析构函数不可以有参数,因此不可以发生重载
  5. 无需手动调用 ,而且只会调用一次。

构造函数的分类和调用:

//构造函数的分类和调用
//分类: 按照参数分类   无参构造 和有参构造

#include
using namespace std;
class person
{
public://构造函数person(){cout << "person 无参构造函数的调用" << endl;}person(int a){age = a;cout << "person有参构造函数调用:" << endl;cout << "age = " << age << endl;}//析构函数~person(){cout << "person 析构函数的调用" << endl;}
public:int age;
};
void func() //括号法调用 :
{/*调用默认无参构造函数时: 不要加上括号  person p1();编译器会自动认为是函数的声明,而不是在创建对象。*/person p1; // 无参构造函数的调用person p2(10); //有参构造函数的调用person p3(p2);// 拷贝构造函数的调用cout << "输出p3拷贝p2后age的值" << p3.age << endl;
}
void func02()  //  显式法调用:
{person p1;person p2 = person(10);person p3 = person(p2);//person(10);// 匿名对象  :调用后就会立刻销毁//不要利用拷贝构造函数初始化匿名对象 , person(p3);//编译器会认为 person p3 重定义 : person (p3) == person p3;
}
void func03()//隐式调用
{person p4 = 10;  //有参 //编译器会自动转换为:  person p4 = person(10);person p5 = p4;//编译器自动转换为:  person p5 = person(p4);
}
int main()
{//func(); //括号法调用//试着输出 p3拷贝后的 age 值   不可以!!  //因为person 的 对象p3  是在 void函数中定义的所以主函数中无法访问//func02();  // 显式调用func03(); //隐式调用}

拷贝构造函数调用时机:

c++ 中拷贝构造函数调用时机通常有三种情况:
① 使用一个已经创建完毕的对象初始化一个新对象
②值传递的方式给函数参数返回传值
③ 以值的方式返回局部变量

#include
using namespace std;class person
{
public:person(){cout << "person无参构造函数的调用" << endl;}person(int age){m_age = age;cout << "person有参构造函数的调用" << endl;}~person(){cout << "person析构函数的调用" << endl;}
person(const person& p)
{m_age = p.m_age ;   //这里一定要注意:如果拷贝构造函数不去接受传入的数据,则输出时会显示乱码cout << "person拷贝构造函数的调用" << endl;
}
int m_age;
};
void func01()  //① 使用一个已经创建完毕的对象初始化一个新对象
{person p1(10);cout << "输出p1.age=" << p1.m_age << endl;person p2(p1);cout << "拷贝后输出p2.age = " <

构造函数的调用规则:

默认情况下,c++编译器至少给一个类添加三个函数

1.默认构造函数(无参,函数体为空)

2.默认析构函数(无参,函数体为空) 因为析构函数不可以发生重载

3.默认拷贝构造函数,对属性进行值拷贝

构造函数调用规则如下 (高级屏蔽低级,低级提供高级)

1.如果用户定义有参构造函数,c++不再提供默认无参构造。依然提供拷贝构造

如果我们自己不写默认构造函数,则编译器不会提供默认构造函数,会编译错误

2.如果用户定义拷贝构造函数,c++不再 提供其他构造函数。

如果我们自己不写,则c++不再提供默认构造和析构函数 ,会编译报错                               

深拷贝与浅拷贝 

浅拷贝:简单的赋值拷贝操作(编译器自带的)

深拷贝:在堆去重新申请空间,进行拷贝操作 (要我们自己去定义一个拷贝函数)   

如果不利用深拷贝在堆区创建新内存,会导致浅拷贝带来的重复释放堆区问题  

 代码:

#include
using namespace std;class person
{public:int m_age;int *m_height;   //用了指针 就需要在堆区自己开辟一条内存person ()//默认构造{cout <<"默认构造函数的调用"<

总结:如果属性有在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的问题

析构函数中检验是否为空指针的部分可以用:

if (ptr == nullptr) {// 检查指针是否为空std::cout << "指针为空" << std::endl;
}

 初始化列表:

初始化列表的几种方法:

第一种: 传统方法:

  person(int a,int b,int c)  //传统方法初始化{m_a =a;m_b =b;m_c =c;}

第二种:列表法:

 person(int a,int b,int c):m_a(a),m_b(b),m_c(c) {}
//也可以直接写成 person(int a,int b,int c):m_a(13),m_b(14),m_c(520) {} 但是不灵活,值设定有局限性。

综合:

#include
using namespace std;class person
{
public:int m_a;int m_b;int m_c;
//  person(int a,int b,int c)  //传统方法初始化
//  {
//      m_a =a;
//      m_b =b;
//      m_c =c;
//  }//列表法:person(int a,int b,int c):m_a(a),m_b(b),m_c(c) {}//也可以直接写成 person(int a,int b,int c):m_a(13),m_b(14),m_c(520) {} 但是不灵活,值设定有局限性。
};
void func01()
{person p(13,14,520);cout << "赋值后的值为:"<

类对象作为类成员: 

语法: (与结构体嵌套类似) 

class  A{    }
class B
{
A a;
}

B 类中有对象A作为成员, A为对象成员.

创建对象时: 副类的构造函数先调用, 主类的构造函数后调用

释放对象时:主类的析构函数先调用,副类的析构函数后调用

#include
using namespace std;
#include
class phone
{
public:string pname;phone (string pname){m_phonename = pname;cout <<"副类的构造函数调用"<

静态成员变量:

静态成员 :静态成员在成员变量和成员函数前加上关键字static,称为静态成员

静态成员分为:

静态成员变量: 

1.所有对象共享同一份数据

静态成员变量不属于某个对象上 ,所有对象都同用一份数据。

2.在编译阶段分配内存(全局区

3.类内声明 ,类外初始化

类外初始化 : 数据类型  类名 :: 成员名 =  初始化数值;

4.只能访问公有权限的static成员,私有static成员在类外不可以访问

5.静态成员变量访问的两种方式:

//1、通过对象
Person p1;
p1.m_A = 100;
cout << "p1.m_A = " << p1.m_A << endl;
//2、通过类名   :  类名 :: 成员名
cout << "m_A = " << Person::m_A << endl;
//cout << "m_B = " << Person::m_B << endl; //私有权限访问不到

整体代码:

#include
using namespace std;
class person
{
public:static int a ;
private:
static int m_a;
};
int person :: a = 100;
int person :: m_a = 120;
void func()
{person p;cout <<"用成员在public中调用:"<

静态成员函数:

所有对象共享同一个函数

1.怎么在类外访问静态成员函数

2.静态成员函数只能访问静态成员变量

class Person
{public://静态成员函数特点://1 程序共享一个函数//2 静态成员函数只能访问静态成员变量static void func(){cout << "func调用" << endl;m_A = 100;//m_B = 100; //错误,不可以访问非静态成员变量}static int m_A; //静态成员变量int m_B; // 
private://静态成员函数也是有访问权限的static void func2(){cout << "func2调用" << endl;}
};
int Person::m_A = 10;void test01()
{//静态成员变量两种访问方式//1、通过对象Person p1;p1.func();//2、通过类名Person::func();//Person::func2(); //私有权限访问不到
}int main() {test01();system("pause");return 0;
}

 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章