当前位置:   article > 正文

面向对象——继承(c++)_c++ 结构体继承

c++ 结构体继承

目录

一、什么是继承

1.1、继承是什么

1.2、继承的概念与定义

二、继承的设计

由基类派生出派生类的定义一般形式为:

举例:

三、struct(结构体) 与 class(类) 在继承中的区别

四、c++继承的理解

4.1继承父类的派生类成员属性

4.1.1设计代码

4.1.2内存分配

4.1.3能否理解为派生类继承后拥有基类的成员属性?

4.2公有继承、私有继承、保护继承(派生类类成员函数访问)

4.2.1问题分析及代码设计

4.2.2 三种继承(类成员函数访问)

保护继承:

私有继承:

4.2.3总结:

4.3三种继承(继承的对象和成员直接关系)

4.3.1问题分析、代码设计

4.3.2结果分析

​4.3.3总结

4.4三种继承(外部函数和成员函数的区别)

4.4.1问题分析、代码设计

4.4.2结果分析

4.4.3总结

4.5三层继承关系

4.5.1问题分析、代码设计

4.5.2结果分析

 4.5.3总结

4.6继承中的同名隐藏

4.6.1问题分析、代码设计;

4.6.2结果分析

 4.6.3总结

4.7切片问题

4.7.1问题分析、代码设计

4.7.2结果显示

 4.7.3总结

4.7.4 问题一:那如果把上述代码中的参数列表初始化改为如下;会不会改变?

4.7.5思考:基类能否给派生类成员赋值?

4.8拷贝构造、赋值函数是否具有继承性

4.8拷贝构造函数分析

4.8.2代码分析

4.8.3怎样才能调用基类的拷贝构造?


一、什么是继承

1.1、继承是什么

继承(inheritance) 机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础,上进行扩展,增加功能。这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构。体现了由简单到复杂的认识过程。百度百科(继承)

1.2、继承的概念与定义

    通过继承(inheritance)的机制可对类(class) 分层,提供类型/子类型的关系。
        C+ +通过类派生(class derivation)的机制来支持继承。被继承的类称为基类(base class)或超类(superclass),新产生的类为派生类(derived class)或子类(subclass) 。基类和派生类的集合称作类继承层次结构(hierarchy) 。

二、继承的设计

由基类派生出派生类的定义一般形式为:

class 派生类名:访问限定符  基类名1《,访问限定符  基类名2,.....访问限定符  基类名n
{
   private:
      // 成员表1     
      // 派生类增加或替代的私有成员
   public:
      // 成员表2    
      // 派生类增加或替代的公有成员
   protected:
      // 成员表3    
      // 派生类增加或替代的保护成员
};//分号不可少

举例:

  1. class Person {
  2. private:
  3. char IdPerson[19]; // 编号
  4. char Name[20]; //姓名
  5. public:
  6. Person() { IdPerson[0] = '\0'; Name[0] = '\0'; }
  7. Person(char* id, char* name) {
  8. strcpy(IdPerson, id);
  9. strcpy(Name, name);
  10. }
  11. ~Person(){};
  12. void PrintPersonInfo()const {
  13. cout << "编号" << IdPerson << '\n' << "姓名:" << Name << endl;
  14. }
  15. };
  16. class Student : public Person
  17. {
  18. private:
  19. char snum[10];
  20. float grade;
  21. public:
  22. Student():Person(){}
  23. Student(char* id, char* name, char* sn) :Person(id, name) {
  24. strcpy(snum, sn);
  25. grade = 0.0;
  26. }
  27. ~Student(){}
  28. void PrintStudentInfo()const {
  29. PrintPersonInfo();
  30. cout << "学号: " << snum << "\n" << "成绩: " << grade << endl;
  31. }
  32. void SetGrade(float ft) {
  33. grade = ft;
  34. }
  35. };

总结:派生反映了事物之间的联系,事物的共性与个性之间的关系。派生与独立设计若干相关的类, 前者工作量少,复的部分可以从基类继承来,不需要单独编程。

三、struct(结构体) 与 class(类) 在继承中的区别

  • 1)struct默认属性是公有的,class默认属性是私有的。
  • 2)struct设计一个类型是把它当作一个集合来看待,class设计类型的时候把它当作一个对象来看待。
  • 3)派生类struct在继承的时候缺省访问限定符,就会默认为公有继承,即使继承的是一个class类,也是默认公有继承。如果是派生类class在继承的时候,缺省访问限定符,默认是私有继承。

四、c++继承的理解

4.1继承父类的派生类成员属性

4.1.1设计代码

  • 基类     Object  拥有 整形  value,num ;
  • 派生类  base    拥有 整形  sum ,  fib;

具体实现如下:

  1. class Object {
  2. public:
  3. int value;
  4. int num;
  5. public:
  6. Object(int x = 0, int y = 0) :value(x), num(y) {
  7. cout << "Create Object :" << this << endl;
  8. }
  9. };
  10. class Base :public Object {
  11. public:
  12. int sum;
  13. int fib;
  14. public:
  15. Base(int a = 0, int b = 0) :sum(a), fib(b) {
  16. cout << "Create Base :" << this << endl;
  17. }
  18. };
  19. int main() {
  20. Base base1;
  21. }

4.1.2内存分配

4.1.3能否理解为派生类继承后拥有基类的成员属性?

如上图可以把Base派生类分为三部分,如下图:

 所以对于派生类来说有三个成员:隐藏基类对象、sum、flag成员。

4.2公有继承、私有继承、保护继承(派生类类成员函数访问)

4.2.1问题分析及代码设计

探讨各种继承关系之间的派生类对基类成员的访问属性;可以设计如下代码 ;用派生类的fun函数去调用基类的成员;其中  ax是私有成员  ay 保护成员  az是公有成员

类A如下所示:

  1. class A {
  2. private:
  3. int ax;
  4. protected:
  5. int ay;
  6. public:
  7. int az;
  8. public:
  9. A() { ax = ay = az = 0; }
  10. };

类B如下所示:

  1. class B
  2. {
  3. private:
  4. int bx;
  5. protected:
  6. int by;
  7. public:
  8. int bz;
  9. public:
  10. B() { bx = by = bz = 1; }
  11. void fun() {
  12. ax = 10; ay = 20; az = 30;
  13. }
  14. };

4.2.2 三种继承(类成员函数访问)

公有继承:

保护继承:

私有继承:

4.2.3总结:

在继承中;不管那种继承方式私有成员在类内类外都不可访问;

4.3三种继承(继承的对象和成员直接关系)

4.3.1问题分析、代码设计

假设 继承的派生类中含有基类的对象,例如如上派生类代码改为:

  1. class B :public A
  2. {
  3. private:
  4. int bx;
  5. A a;
  6. protected:
  7. int by;
  8. public:
  9. int bz;
  10. public:
  11. B() { bx = by = bz = 1; }
  12. void fun() {
  13. //ax = 10; ay = 20; az = 30;
  14. //a.ax = 15; a.ay = 25; a.az = 35;
  15. }
  16. };

那么将A a定义在派生类的公有属性、保护属性、私有属性中有什么不同?

4.3.2结果分析

内存图:

 在私有属性中中定义;

 在保护属性中定义:

 在公有属性中:

 4.3.3总结

在派生类中声明基类的具有名对象;无论该对象处于什么属性中;只能访问具有名对象的公有属性;

4.4三种继承(外部函数和成员函数的区别)

4.4.1问题分析、代码设计

如果在派生类外的函数中访问派生类的属性会出现什么情况;例如在主函数(main)中给派生类对象赋值会出现什么结果?那种通过不了?为什么? 如果

主函数如图所示:

  1. int main() {
  2. B b;
  3. b.bz - 100;
  4. b.az - 100;
  5. b.ay - 100;
  6. b.a.az - 100;
  7. b.a.ay - 100;
  8. return 0;
  9. }

4.4.2结果分析

情况一:A a在派生类的公有属性中:派生类公有继承基类

 情况二:派生类私有继承基类

 情况三:将A a定义在保护和私有中A a将都不可访问;

  

4.4.3总结

外部函数可以访问类中的公有成员,可以访问公有继承中的公有成员,可以访问公有成员对象中的公有成员。

4.5三层继承关系

4.5.1问题分析、代码设计

三层继承其实和两层继承差不多;理解好其中的关系即可;现在设计三个类;

类A:

  1. class A {
  2. private: int ax;
  3. protected: int ay;
  4. public: int az;
  5. public:
  6. A() { ax = ay = az = 0; }
  7. };

类B:

  1. class B
  2. {
  3. private: int bx;
  4. protected: int by;
  5. public: int bz;
  6. public: B() { bx = by = bz = 1; }
  7. };

类C:

  1. class C
  2. {
  3. private: int cx;
  4. protected: int cy;
  5. public: int cz;
  6. };

假设我们改变其中的继承关系会怎样影响类C中的的访问权限?

4.5.2结果分析

情况一:B公有继承A;C公有继承B类;

内存图:

 fun函数中都能访问;但是A类和B类的私有成员不能访问;

情况二:将B类公有继承A类改为私有继承A类会怎样;

情况三: 将B类私有继承A类改为保护继承A类会怎样;

 4.5.3总结

在多层继承中;派生类能否访问基类的对象成员;在于基类继承的基类成员是什么属性;如果基类继承私有继承;那么在基类的成员属性就为基类的私有成员;而私有成员被继承下来是不可访问的;

4.6继承中的同名隐藏

4.6.1问题分析、代码设计;

看如下代码的运行;思考运行结果ax=100是赋值给基类A还是派生类B;

  1. class A
  2. {
  3. protected:
  4. int ax;
  5. public:
  6. A() :ax(0) {}
  7. };
  8. class B :public A
  9. {
  10. private:
  11. int ax;
  12. public:
  13. B():ax(10){}
  14. void fun() {
  15. ax = 100;
  16. }
  17. };
  18. int main() {
  19. B b;
  20. b.fun();
  21. }

内存图:

 那如果调用fun()函数了;我们都知道;会首先构建基类对象对象,那赋值是不是也先给基类对象赋值?

4.6.2结果分析

 4.6.3总结

如果派生类与基类有相同的函数名字或者对象名字;派生类会访问自己的对象(就近原则);或者理解为编译期时候派生类对象隐藏了基类同名对象;所谓同名隐藏;

那怎么可以访问了?回答:假设类的作用域;

4.7切片问题

4.7.1问题分析、代码设计

在继承中,派生类对象是否可以给基类对象赋值?

  1. class Object
  2. {
  3. private:
  4. int value;
  5. public:
  6. Object(int x = 10) :value(x) {}
  7. ~Object() {}
  8. };
  9. class Base :public Object {
  10. private:
  11. int num;
  12. public:
  13. Base(int x = 0) :num(x), Object(x + 10) {}
  14. ~Base() {};
  15. };

如果main函数作如下处理会不会改变基类的对象值?

  1. Object obja(100);
  2. Base s1(10);

4.7.2结果显示

 4.7.3总结

派生类在初始化时,通过参数列表改变基类的值,会发生切片现象;但是必须在公有继承之下;

4.7.4 问题一:那如果把上述代码中的参数列表初始化改为如下;会不会改变?

  1. class Base :public Object {
  2. private:
  3. int num;
  4. public:
  5. Base(int x = 0) :num(x)
  6. {
  7. Object(x + 10);
  8. }
  9. ~Base() {};
  10. };

4.7.5思考:基类能否给派生类成员赋值?

4.8拷贝构造、赋值函数是否具有继承性

4.8拷贝构造函数分析

代码如下;是想用base能base2赋值;能不能调动基类的拷贝构造?

  1. class Object
  2. {
  3. private:
  4. int value;
  5. public:
  6. Object(int x = 10) :value(x) { cout << "Create Object :" << this << endl; }
  7. ~Object() { cout << "Destroy Object :" << this << endl; }
  8. Object(const Object& obj) :value(obj.value) {
  9. cout << "Copy Create Object :" << this << endl;
  10. }
  11. };
  12. class Base :public Object {
  13. private:
  14. int num;
  15. public:
  16. Base(int x = 0) :num(x), Object(x + 10) { cout << "Create Base:" << this << endl; }
  17. ~Base() { cout << "Destroy Base: " << this << endl; }
  18. Base(const Base& base) :num(base.num) {
  19. cout << "Copy Creater Base :" << this << endl;
  20. }
  21. };
  22. int main() {
  23. Base base(10);
  24. Base bas2(base);
  25. return 0;
  26. }

4.8.2代码分析

 

 所以并不会去调用基类的拷贝构造函数;也就是说拷贝构造函数不具有继承性;

4.8.3怎样才能调用基类的拷贝构造?

原因是赋值兼容规则;上文有讲述; 4.7


 

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

闽ICP备14008679号