当前位置:   article > 正文

C++ 类和对象

C++ 类和对象

4.1封装

4.1.1封装的意义

 4.1.2struct和class的区别

 4.1.3成员属性设置为私有

  1. class student
  2. {
  3. public:
  4. //设置姓名
  5. void setname(string name);
  6. //获取姓名
  7. string getname();
  8. int getid();
  9. void setidl(string name);
  10. private:
  11. //属性 姓名学号
  12. string name;//可读可写
  13. int id = 18;//只读
  14. string idl;//只写
  15. };
  16. void student::setname(string n)
  17. {
  18. name = n;
  19. }
  20. string student::getname()
  21. {
  22. return name;
  23. }
  24. int student::getid()
  25. {
  26. return id;
  27. }
  28. void student::setidl(string n)
  29. {
  30. idl = n;
  31. }
  32. int main()
  33. {
  34. student p;
  35. p.setname("张三");
  36. p.setidl("蔡徐坤");
  37. cout << "姓名:" << p.getname()<<endl<< "id="<<p.getid()<< endl;
  38. return 0;
  39. }

4.1.4练习

  1. class cube
  2. {
  3. public:
  4. int l;
  5. int h;
  6. int w;
  7. int s()
  8. {
  9. return h * l * 2 + h * w * 2 + w * l * 2;
  10. }
  11. int v()
  12. {
  13. return l * h * w;
  14. }
  15. //利用成员函数来判断是否相等
  16. //只需要传一个参数
  17. //因为:成员调用这个成员函数,成员自身信息都可直接获取,而另一个对象的信息需要通过引用用获取
  18. bool issamebyclass(cube&c)
  19. {
  20. if (l == c.l && w == c.w && h == c.h)
  21. {
  22. return true;
  23. }
  24. return false;
  25. }
  26. };
  27. bool issame(cube& c1, cube& c2)//使用全局函数来判断是否相等
  28. {
  29. if (c1.l == c2.l && c1.w == c2.w && c1.h == c2.h)
  30. {
  31. return true;
  32. }
  33. return false;
  34. }
  35. int main()
  36. {
  37. cube p1;
  38. p1.h = 1;
  39. p1.l = 1;
  40. p1.w = 1;
  41. cube p2;
  42. p2.h = 2;
  43. p2.l = 2;
  44. p2.w = 2;
  45. cout << "p1的面积"<< p1.s()<<"p1的体积"<<p1.v() <<endl;
  46. cout << "p2的面积"<< p2.s() <<"p2的体积"<< p2.v() <<endl;
  47. bool ret= issame( p1, p2);
  48. if (ret)
  49. {
  50. cout << "p1和p2是相等的" << endl;
  51. }
  52. else
  53. {
  54. cout << "p1和p2是不相等的" << endl;
  55. }
  56. bool rete = p1.issamebyclass(p2);
  57. if (rete)
  58. {
  59. cout << "p1和p2是相等的" << endl;
  60. }
  61. else
  62. {
  63. cout << "p1和p2是不相等的" << endl;
  64. }
  65. return 0;
  66. }

 

  1. class point
  2. {
  3. public:
  4. void setx(int a);
  5. void sety(int b);
  6. int getx();
  7. int gety();
  8. private:
  9. int x;
  10. int y;
  11. };
  12. void point::setx(int a)
  13. {
  14. x = a;
  15. }
  16. void point::sety(int b)
  17. {
  18. y = b;
  19. }
  20. int point::getx()
  21. {
  22. return x;
  23. }
  24. int point::gety()
  25. {
  26. return y;
  27. }
  28. class circle
  29. {
  30. public:
  31. void setr(int m);
  32. int getr();
  33. void setcenter(point c);
  34. point getcenter();
  35. private:
  36. int r;
  37. point center;//在类中可以让另一个类作为本来的成员
  38. };
  39. void circle::setr(int m)
  40. {
  41. r = m;
  42. }
  43. int circle::getr()
  44. {
  45. return r;
  46. }
  47. void circle::setcenter(point c)
  48. {
  49. center = c;
  50. }
  51. point circle::getcenter()
  52. {
  53. return center;
  54. }
  55. void isincircle(circle& c,point & p)
  56. {
  57. //计算两点间的距离
  58. int distence =
  59. ((p.getx() - c.getcenter().getx()) * (p.getx() - c.getcenter().getx()))+
  60. ((p.gety() - c.getcenter().gety()) * (p.gety() - c.getcenter().gety()));
  61. //计算半径的平方
  62. int rdistence = c.getr() * c.getr();
  63. if (distence == rdistence)
  64. {
  65. cout << "点在圆上" << endl;
  66. }
  67. else if (distence < rdistence)
  68. {
  69. cout << "点在圆内" << endl;
  70. }
  71. else
  72. {
  73. cout << "点在圆外" << endl;
  74. }
  75. }
  76. int main()
  77. {
  78. circle c;
  79. point center;
  80. point p;
  81. c.setr(10);
  82. //center 必须先初始化出来后才能在圆中使用
  83. center.setx(0);
  84. center.sety(0);
  85. //也就是这一步中的center必须在前面初始化完成它的属性
  86. c.setcenter(center);
  87. p.setx(5);
  88. p.sety(5);
  89. isincircle(c, p);
  90. return 0;
  91. }

4.2对象的初始化和清理

4.2.1构造函数和析构函数 

  1. class person
  2. {
  3. public:
  4. //1.构造函数
  5. person()
  6. {
  7. cout << "person构造函数的调用" << endl;
  8. }
  9. //2.析构函数
  10. ~person()
  11. {
  12. cout << "person析构函数的调用" << endl;
  13. }
  14. };
  15. //构造和析构函数都是必须有的实现,如果我们不提供,编译器会提供一个空实现的构造和析构
  16. void test01()
  17. {
  18. person p;//在栈上的数据,test01执行完毕后,释放这个对象
  19. }
  20. int main()
  21. {
  22. test01();
  23. return 0;
  24. }

4.2.2构造函数的分类及调用

  1. //1.构造函数的分类及调用
  2. //分类
  3. //按参数分类:有参构造 无参构造(默认构造函数)
  4. //按照类型分类:普通构造函数 拷贝构造函数
  5. class person
  6. {
  7. public:
  8. //1.构造函数
  9. person()
  10. {
  11. cout << "person无参构造函数的调用" << endl;
  12. }
  13. person(int a)
  14. {
  15. age = a;
  16. cout << "person有参构造函数的调用" << endl;
  17. }
  18. //拷贝构造函数
  19. person(const person& p)
  20. {
  21. //将传入的这个人身上的所有属性,拷贝到我身上
  22. age = p.age;
  23. cout << "person拷贝构造函数的调用" << endl;
  24. }
  25. //2.析构函数
  26. ~person()
  27. {
  28. cout << "person析构函数的调用" << endl;
  29. }
  30. int age;
  31. };
  32. //调用
  33. void test01()
  34. {
  35. //1.括号法
  36. person p;//默认构造函数
  37. person p2(10);//有参构造函数
  38. person p3(p2);//拷贝构造函数
  39. //注意事项:
  40. //1.调用默认构造函数的时候不要加()
  41. //2.不要利用拷贝构造函数 初始化匿名对象
  42. cout << "p2的年龄为:" << p2.age << endl;
  43. cout << "p3的年龄为:" << p3.age << endl;
  44. //下面这个函数编译器会默认为函数声明,不会认为是在创建对象
  45. //person p1();
  46. //2.显示法
  47. person a1;
  48. person a2 = person(10);
  49. person a3 = person(a2);
  50. person(10);//匿名对象 特点:当前行执行结束后,系统会立即回收掉匿名对象
  51. //不要利用拷贝构造函数 初始化匿名对象 编译器会认为person(p3)======person p3;
  52. //person(p2);
  53. //3.隐式转换法
  54. person p4 = 10;//相当于 写了person pe4=person(10);
  55. person p5 = p4;
  56. }
  57. int main()
  58. {
  59. test01();
  60. return 0;
  61. }

 

 4.2.3拷贝构造函数的调用时机

 

  1. //拷贝构造函数调用时机
  2. //1.使用一个已经创建完毕的对象来初始化一个新对象
  3. //2.值传递的方式给函数参数传值
  4. //3.值方式返回局部对象
  5. class person
  6. {
  7. public:
  8. //1.构造函数
  9. person()
  10. {
  11. cout << "person无参构造函数的调用" << endl;
  12. }
  13. person(int a)
  14. {
  15. age = a;
  16. cout << "person有参构造函数的调用" << endl;
  17. }
  18. //拷贝构造函数
  19. person(const person& p)
  20. {
  21. //将传入的这个人身上的所有属性,拷贝到我身上
  22. cout << "person拷贝构造函数的调用" << endl;
  23. age = p.age;
  24. }
  25. //2.析构函数
  26. ~person()
  27. {
  28. cout << "person析构函数的调用" << endl;
  29. }
  30. int age;
  31. };
  32. //拷贝构造函数调用时机
  33. //1.使用一个已经创建完毕的对象来初始化一个新对象
  34. void test01()
  35. {
  36. person p1(20);
  37. person p2(p1);
  38. cout << "p2的年龄" << p2.age << endl;
  39. }
  40. //2.值传递的方式给函数参数传值
  41. void dowork(person p)
  42. {
  43. }
  44. void test02()
  45. {
  46. person p;
  47. dowork(p);
  48. }
  49. //3.值方式返回局部对象
  50. person dowork02()
  51. {
  52. person p1;
  53. cout << (int*)&p1 << endl;
  54. return person (p1);
  55. }
  56. void test03()
  57. {
  58. person p = dowork02();
  59. cout << (int*)&p << endl;
  60. }
  61. int main()
  62. {
  63. //test01();
  64. //test02();
  65. test03();
  66. return 0;
  67. }

4.2.4构造函数的调用规则

4.2.5深拷贝与浅拷贝

 

  1. //深拷贝与浅拷贝
  2. class person
  3. {
  4. public:
  5. //1.构造函数
  6. person()
  7. {
  8. cout << "person无参构造函数的调用" << endl;
  9. }
  10. person(int a,int h)
  11. {
  12. age = a;
  13. height=new int(h);
  14. cout << "person有参构造函数的调用" << endl;
  15. }
  16. //2.析构函数
  17. ~person()
  18. {
  19. //析构函数,将堆区开辟数据做释放操作
  20. if (height != NULL)
  21. {
  22. delete height;
  23. height = NULL;
  24. }
  25. cout << "person析构函数的调用" << endl;
  26. }
  27. //自己实现拷贝构造函数 解决浅拷贝带来的问题
  28. person(const person& p)
  29. {
  30. cout << "person拷贝构造函数的调用" << endl;
  31. age = p.age;
  32. //深拷贝操作
  33. height=new int(*p.height);
  34. }
  35. int age;
  36. int* height;
  37. };
  38. void test01()
  39. {
  40. person p1(18,160);
  41. cout << "p1的年龄为多大:" << p1.age << "身高为:"<<*p1.height << endl;
  42. person p2(p1);
  43. cout << "p1的年龄为多大:" << p1.age << "身高为:" <<*p2.height << endl;
  44. }
  45. int main()
  46. {
  47. test01();
  48. return 0;
  49. }

4.2.6初始化列表

  1. class person
  2. {
  3. public:
  4. int m_a;
  5. int m_b;
  6. int m_c;
  7. //传统初始化操作
  8. /*person(int a, int b, int c)
  9. {
  10. m_a=a;
  11. m_b=b;
  12. m_c=c;
  13. }*/
  14. //初始化列表初始化属性
  15. person(int a,int b,int c):m_a(a),m_b(b),m_c(c)
  16. {}
  17. };
  18. void test01()
  19. {
  20. //person p(10, 20, 30);
  21. person p(30,20,10);
  22. cout << "m_a=" << p.m_a << endl;
  23. cout << "m_b=" << p.m_b << endl;
  24. cout << "m_c=" << p.m_c << endl;
  25. }
  26. int main()
  27. {
  28. test01();
  29. system("pause");
  30. return 0;
  31. }

 

4.2.7类对象作为类成员

  1. class phone
  2. {
  3. public:
  4. //手机品牌名称
  5. string m_pname;
  6. phone(string pname)
  7. {
  8. m_pname = pname;
  9. }
  10. };
  11. class person
  12. {
  13. public:
  14. //phone m_phone=pname; 隐式转换法
  15. person(string name, string pname) :m_name(name), m_phone(pname)//phone m_phone=pname
  16. {
  17. }
  18. //姓名
  19. string m_name;
  20. //手机
  21. phone m_phone;
  22. };
  23. void test01()
  24. {
  25. person p("张三", "苹果MAX");
  26. cout << p.m_name << "拿着:" << p.m_phone.m_pname << endl;
  27. }
  28. int main()
  29. {
  30. test01();
  31. system("pause");
  32. return 0;
  33. }

 

 4.2.8静态成员

 

 静态成员变量

  1. class Person
  2. {
  3. public:
  4. //1.所有对象都共同享用同一份数据
  5. //2.编译阶段就分配内存
  6. //3.类内声明,类外初始化操作
  7. static int m_A;
  8. //静态成员变量也是有访问权限的
  9. private:
  10. static int m_B;
  11. };
  12. int Person::m_A=100;
  13. void test01()
  14. {
  15. Person p;
  16. cout << p.m_A << endl;
  17. Person p2;
  18. p2.m_A = 200;
  19. cout << p.m_A << endl;
  20. }
  21. void test02()
  22. {
  23. //静态成员变量 不属于某一个对象上,所有对象都共享同一份数据
  24. //因此静态成员变量有两种访问方式
  25. //1.通过对象进行访问
  26. Person p;
  27. cout << p.m_A << endl;
  28. //2.通过类名进行访问
  29. cout << Person::m_A << endl;
  30. //cout << Person::m_b << endl;//类外访问不到私有静态成员变量
  31. }
  32. int main()
  33. {
  34. //test01();
  35. test02();
  36. system("pause");
  37. return 0;
  38. }

 静态成员函数

  1. class Person
  2. {
  3. public:
  4. //静态成员函数
  5. //所有对象共享同一个函数
  6. //静态成员函数只能访问静态成员变量
  7. static void func()
  8. {
  9. //m_B = 200;//静态成员函数不可以访问 非静态成员变量,无法区分到底是哪个对象的m_B的属性
  10. m_A = 100;//静态成员函数可以访问 静态成员变量
  11. cout << "static void func调用" << endl;
  12. }
  13. static int m_A;
  14. int m_B;
  15. //静态成员函数也是有访问权限的
  16. private:
  17. static void func2()
  18. {
  19. cout << "static void func2调用" << endl;
  20. }
  21. };
  22. int Person::m_A;
  23. void test02()
  24. {
  25. //静态成员函数 两种访问方式
  26. //1.通过对象进行访问
  27. Person p;
  28. p.func();
  29. //2.通过类名进行访问
  30. Person::func();
  31. //Person::func2();//类外访问不到私有静态成员函数
  32. }
  33. int main()
  34. {
  35. //test01();
  36. test02();
  37. system("pause");
  38. return 0;
  39. }

4.3C++对象模型和this指针

4.3.1成员变量和成员函数分开存储

  1. //成员变量 和成员函数是分开存储的
  2. class Person
  3. {
  4. int m_A;//非静态成员变量 属于类的对象上的数据
  5. static int m_B;//静态成员变量 不属于类的对象上
  6. void func(){}//非静态成员函数 不属于类的对象上
  7. static void func2(){}//静态成员函数 不属于类的对象上
  8. };
  9. int Person::m_B;
  10. void test01()
  11. {
  12. Person p;
  13. //空对象占用的内存空间为: 1
  14. //C++编译器会给每个空对象也分配字节空间,是为了区分空对象占内存的位置
  15. //每个空对象也应该有一个独一无二的内存地址
  16. cout << "size of p =" << sizeof(p) << endl;
  17. }
  18. void test02()
  19. {
  20. Person p1;
  21. //
  22. cout << "size of p =" << sizeof(p1) << endl;
  23. }
  24. int main()
  25. {
  26. test01();
  27. test02();
  28. system("pause");
  29. return 0;
  30. }

 4.3.2 this指针概念

  1. class Person
  2. {
  3. public:
  4. Person(int age)
  5. {
  6. //this 指针指向的是 被调用的成员函数所属的对象
  7. this->age = age;
  8. }
  9. Person& PersonAddAge(Person& p)//返回它的本体需要使用引用的方式作为返回
  10. {
  11. this->age += p.age;
  12. //this 是指向p2的指针,而*p2就是这个对象本体
  13. return *this;
  14. }
  15. int age;
  16. };
  17. //1.解决名称冲突
  18. void test01()
  19. {
  20. Person p1(18);
  21. cout << "p1的年龄为:" << p1.age << endl;
  22. }
  23. //2.返回对象本身用*this
  24. void test02()
  25. {
  26. Person p1(10);
  27. Person p2(10);
  28. //链式编程思想
  29. p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);
  30. cout << "p2的年龄为:" << p2.age << endl;
  31. }
  32. int main()
  33. {
  34. //test01();
  35. test02();
  36. return 0;
  37. }

 

4.3.3空指针访问成员函数

 

  1. class Person
  2. {
  3. public:
  4. void showClassName()
  5. {
  6. cout << "this Person class" << endl;
  7. }
  8. void showClassAge()
  9. {
  10. //报错原因是因为传入的指针为NULL
  11. if (this==NULL)
  12. {
  13. return;
  14. }
  15. cout << "age=" <<m_age<< endl;
  16. }
  17. int m_age;
  18. };
  19. void test01()
  20. {
  21. Person* p = NULL;
  22. p->showClassName();
  23. p->showClassAge();
  24. }
  25. int main()
  26. {
  27. test01();
  28. //test02();
  29. return 0;
  30. }

4.3.4const修饰成员函数

 

  1. //常函数
  2. class Person
  3. {
  4. public:
  5. //this指针的本质 是指针常量 指针的指向是不可以修改的
  6. //const Person * const this;
  7. //在成员函数后面加const,修饰的是this指向,让指针指向的值也不可以修改
  8. void ShowPerson()const
  9. {
  10. //this->m_A = 100;
  11. //this->NULL;//this指针不可以修改指针的指向的
  12. }
  13. void func()
  14. {}
  15. int m_A;
  16. mutable int m_B;//特殊变量,即使在常函数中,也可以修改这个值,加关键字mutable
  17. };
  18. void test01()
  19. {
  20. Person p;
  21. p.ShowPerson();
  22. }
  23. //常对象
  24. void test02()
  25. {
  26. const Person p;//在对象前加const,变为常对象
  27. //p.m_A=100; 不可修改
  28. p.m_B = 100; //特殊值,在常对象下也可以修改
  29. //常对象只能调用常函数
  30. p.ShowPerson();
  31. //p.func();//常对象 不可以调用普通成员函数,因为普通成员函数可以修改属性
  32. }
  33. int main()
  34. {
  35. test01();
  36. //test02();
  37. return 0;
  38. }

4.4 友元

4.4.1全局函数做友元

 

  1. //建筑物类
  2. class Building
  3. {
  4. //goodGay全局函数是Building的好朋友,可以访问Building中私有成员
  5. friend void goodGay(Building& building);
  6. public:
  7. string m_SettingRoom;
  8. Building()
  9. {
  10. m_SettingRoom = "客厅";
  11. m_BedRoom = "卧室";
  12. }
  13. private:
  14. string m_BedRoom;
  15. };
  16. //全局函数
  17. void goodGay(Building& building)
  18. {
  19. cout << "好基友的全局函数正在访问:"<<building.m_SettingRoom << endl;
  20. cout << "好基友的全局函数正在访问:" << building.m_BedRoom << endl;
  21. }
  22. void test01()
  23. {
  24. Building building;
  25. goodGay(building);
  26. }
  27. int main()
  28. {
  29. test01();
  30. system("pause");
  31. return 0;
  32. }

 

 4.4.2类做友元(代码有点问题)

  1. class Building;
  2. class GoodGay
  3. {
  4. public:
  5. Building* building;
  6. public:
  7. GoodGay()
  8. {
  9. //创建建筑物对象
  10. building = new Building;
  11. }
  12. void visit()
  13. {
  14. cout << "好基友类正在访问:" << building->m_SettingRoom << endl;
  15. cout << "好基友类正在访问:" << building->m_BedRoom << endl;
  16. }
  17. };
  18. class Building
  19. {
  20. //GoodGay类是本来的好朋友,可以访问本类中私有成员
  21. friend class GoodGay;
  22. public:
  23. string m_SettingRoom;
  24. Building()
  25. {
  26. m_SettingRoom = "客厅";
  27. m_BedRoom = "卧室";
  28. }
  29. private:
  30. string m_BedRoom;
  31. };
  32. void test01()
  33. {
  34. GoodGay gg;
  35. gg.visit();
  36. }
  37. int main()
  38. {
  39. test01();
  40. system("pause");
  41. return 0;
  42. }

 

 4.4.3成员函数做友元

  1. class Building;
  2. class GoodGay
  3. {
  4. public:
  5. GoodGay();
  6. void visit();//让visit函数可以访问Building中私有成员
  7. void visit2();//让visit2函数不可以访问Building中私有成员
  8. Building* building;
  9. };
  10. class Building
  11. {
  12. public:
  13. //告诉编译器 GoodGay中的visit()函数作为本类的好朋友,可以访问私有成员
  14. friend void GoodGay::visit2();
  15. Building();
  16. string m_SettingRoom;//客厅
  17. private:
  18. string m_BedRoom;//客厅
  19. };
  20. //类外实现成员函数
  21. Building::Building()
  22. {
  23. m_SettingRoom = "客厅";
  24. m_BedRoom = "卧室";
  25. }
  26. GoodGay::GoodGay()
  27. {
  28. building = new Building;
  29. }
  30. void GoodGay::visit()//让visit函数可以访问Building中私有成员
  31. {
  32. cout << "visit函数正在访问" << building->m_SettingRoom << endl;
  33. }
  34. void GoodGay::visit2()
  35. {
  36. cout << "visit函数正在访问" << building->m_BedRoom << endl;
  37. }
  38. void test01()
  39. {
  40. GoodGay gg;
  41. gg.visit();
  42. gg.visit2();
  43. }
  44. int main()
  45. {
  46. test01();
  47. system("pause");
  48. return 0;
  49. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/221947
推荐阅读
相关标签
  

闽ICP备14008679号