• C++之继承、派生


    目录

    1.继承的概念与定义

    2.层次概念是计算机的重要概念:

    3.私有的能被继承,不能被访问

     4.继承的三步骤

    1.继承语法

    2.继承例子

    5.有继承和组合的构造顺序---内存布局

    6.继承之下的赋值运算符重载

    1.基础知识

     2.Person、Student例子

    7.一个类被多个类继承


    1.继承的概念与定义

    继承和派生:(继承和派生一体两面)

    继承(inheritance)机制:是类型层次结构设计中实现代码的复用重要手段。

    class 子类: 继承权限 基类
     {
    };
    继承:
    * 1.一个类自动拥有了来自另外一个类的属性和方法
    * 2.一个类是一个类
    * 层次关系-继承、派生

    继承:
    1、基类的处理构造和析构之外,其他的全盘继承
    2、是否能被子类的成员函数访问
    3、是否能被外界访问

    基类的权限        public           protected         private——继承权限

     public               public            protected         private
     protected         protected      protected          private
     private             不可访问       不可访问          不可访问

    派生:保持原有类特性的基础上进行扩展,增加新属性和新方法,从而产生新的类型。

    面向对象程序设计中,继承和派生是构造出新类型的过程。呈现类型设计的层次结构,体现了程 序设计人员对现实世界由简单到复杂的认识过程。

    2.层次概念是计算机的重要概念:

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

    由基类派生出,派生类的设计形式为:

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

    3.私有的能被继承,不能被访问

    1. class A
    2. {
    3. public:
    4. int m_i;
    5. void print()
    6. {
    7. cout << "A::print" << endl;
    8. }
    9. protected:
    10. int m_j;
    11. private:
    12. int m_k;
    13. };
    14. class B :public A
    15. {
    16. void set()
    17. {
    18. m_i = 10;
    19. m_j = 30;
    20. //m_k = 15;
    21. }
    22. };
    23. class C :protected A
    24. {
    25. void set()
    26. {
    27. m_i = 10;
    28. m_j = 30;
    29. //m_k = 15;
    30. }
    31. };
    32. class D :private A
    33. {
    34. void fn()
    35. {
    36. m_i = 10;
    37. m_j = 30;
    38. //m_k = 15;
    39. }
    40. };
    41. class CC :protected C
    42. {
    43. public:
    44. void ff()
    45. {
    46. m_i = 12;
    47. m_j = 23;
    48. //m_k = 15;
    49. }
    50. };
    51. class DD :public D
    52. {
    53. public:
    54. void ff()
    55. {
    56. //m_i = 12;
    57. //m_j = 23;
    58. //m_k = 15;
    59. }
    60. };
    61. //如果是私有继承,只能继承,不能使用
    62. //继承除了构造和析构全盘接收
    63. void main()
    64. {
    65. cout << sizeof(B) << endl;
    66. B b;
    67. b.print();
    68. b.m_i = 12;
    69. //b.m_j = 23;
    70. //b.m_k = 34;
    71. C c;
    72. //c将属性m_i变成protected
    73. c.m_i = 12;
    74. c.m_j = 23;
    75. c.m_k = 34;}

    class B :public  A//如果没有说明,默认私有继承
     //m_k = 15;//私有的能被继承,不能被访问
    class DD :public D
    {
    public:
        void ff()
        {
            //在上一次继承被私有化了,不能再继承、访问
            //m_i = 12;
            //m_j = 23;
            //m_k = 15;
        }
    };
    //b.m_j = 23;//保护的在外界不能使用
    C c;
    //c将属性m_i变成protected
    c.m_k = 34;//将C被保护继承

     4.继承的三步骤

    * 1.除了构造和析构全盘接收
    * 2.改写
    * 3.添加子类特有的

    1.继承语法

    class 派生类名:[继承方式] 基类名{ 派生类新增加的成员 };

    代码如下:

    1. class A
    2. {
    3. public:
    4. A()
    5. {
    6. cout << "A" << endl;
    7. }
    8. void print()
    9. {
    10. cout << "A::print" << endl;
    11. }
    12. ~A()
    13. {
    14. cout << "~A" << endl;
    15. }
    16. private:
    17. int m_i;
    18. };
    19. class B : public A
    20. {
    21. public:
    22. B()
    23. {
    24. cout << "B" << endl;
    25. }
    26. ~B()
    27. {
    28. cout << "~B" << endl;
    29. }
    30. private:
    31. int m_j;
    32. };
    33. void main()
    34. {
    35. B b;
    36. }

     

     因为子类继承父类的时候,先运行父类构造函数;具体的说就是运行父类时就会先“调用”父类的构造函数,注意“调用”和继承不是一个含义,实质上是“自动运行”。

    2.继承例子

    1. class Person
    2. {
    3. public:
    4. Person(int num,const char*name,char sex) :m_num(num), m_sex(sex)
    5. {
    6. m_name = new char[strlen(name) + 1];
    7. strcpy_s(m_name, strlen(name) + 1, name);
    8. }
    9. ~Person()
    10. {
    11. if (m_name != NULL)
    12. {
    13. delete[]m_name;
    14. m_name = NULL;
    15. }
    16. }
    17. Person(const Person& p) :m_num(p.m_num), m_sex(p.m_sex)
    18. {
    19. m_name = new char[strlen(p.m_name) + 1];
    20. strcpy_s(m_name, strlen(p.m_name) + 1, p.m_name);
    21. }
    22. void Show()
    23. {
    24. cout << m_num << " " << m_name << " " << m_sex << endl;
    25. }
    26. private:
    27. int m_num;
    28. char* m_name;
    29. char m_sex;
    30. };
    31. class Student :public Person
    32. {
    33. public:
    34. Student(int num, const char* name, char sex, float score)
    35. :Person(num,name,sex),m_score(score)
    36. {
    37. }
    38. Student(Student& s) :Person(s)
    39. {
    40. m_score = s.m_score;
    41. }
    42. void Print()
    43. {
    44. Show();
    45. cout << m_score << endl;
    46. }
    47. private:
    48. float m_score;
    49. };
    50. void main()
    51. {
    52. Student s1(1001, "zhaowawa", 'f', 15);
    53. s1.Print();
    54. Student s2(s1);
    55. s2.Print();
    56. }

     

     Student类公有继承了Person类中的num、name、sex,并且扩展了score。

    5.有继承和组合的构造顺序---内存布局

    * 1.先按照继承顺序调用基类构造
    * 2.按照组合顺序调用组合的构造
    * 3.调用自己的构造

    1. class CPU
    2. {
    3. public:
    4. CPU() { cout << "CPU" << endl; }
    5. };
    6. class KB
    7. {
    8. public:
    9. KB() { cout << "KB" << endl; }
    10. };
    11. class Mouse
    12. {
    13. public:
    14. Mouse() { cout << "Mouse" << endl; }
    15. };
    16. class Computer
    17. {
    18. public:
    19. Computer() { cout << "Computer" << endl; }
    20. private:
    21. CPU cpu;
    22. KB kb;
    23. Mouse ms;
    24. };
    25. class Touch
    26. {
    27. public:
    28. Touch() { cout << "Touch" << endl; }
    29. };
    30. class Laptop :public Computer
    31. {
    32. public:
    33. Laptop() { cout << "Laptop" << endl; }
    34. private:
    35. Touch tc;
    36. };
    37. void main()
    38. {
    39. Laptop lp;
    40. }

    1.调用基类,2.按照组合顺序得到:

    CPU
    KB
    Mouse
    Computer

    3.调用自己的构造

    Touch
    Laptop

    6.继承之下的赋值运算符重载

    1.基础知识

    1. class A
    2. {
    3. public:
    4. void Print()
    5. {
    6. cout << "A::Print" << endl;
    7. }
    8. protected:
    9. int m_i;
    10. };
    11. /*
    12. *隐藏:
    13. */
    14. class B :public A
    15. {
    16. public:
    17. //B::Print将A::Print隐藏了
    18. void Print()
    19. {
    20. cout << "B::Print" << endl;
    21. cout << m_i << " " << A::m_i << endl;
    22. }
    23. void set()
    24. {
    25. m_i = 10;
    26. A::m_i = 20;
    27. }
    28. protected:
    29. int m_i;
    30. };
    31. void main()
    32. {
    33. A a;
    34. B b;
    35. a.Print();
    36. b.set();
    37. b.A::Print();
    38. b.Print();
    39. cout << sizeof(A) << endl;//4
    40. cout << sizeof(B) << endl;//8
    41. }

    //B::Print将A::Print隐藏了

    A::Print      a.Print();
    A::Print      b.A::Print();//B调用A::Print
    B::Print      b.Print();
    10 20         b.set();、b.Print();
    4                int m_i;的大小
    8                既继承了A中的m_i,B自己构造了成员

     2.Person、Student例子

    1. class Person
    2. {
    3. public:
    4. Person() :m_sex('f'), m_age(20)
    5. {
    6. m_name = new char[1];
    7. *m_name = '\0';
    8. cout << "Person()" << endl;
    9. }
    10. Person(const char* name,char sex,int age):m_sex(sex), m_age(age)
    11. {
    12. m_name = new char[strlen(name) + 1];
    13. strcpy_s(m_name, strlen(name) + 1, name);
    14. }
    15. Person(Person& p) :m_sex(p.m_sex), m_age(p.m_age)
    16. {
    17. m_name = new char[strlen(p.m_name) + 1];
    18. strcpy_s(m_name, strlen(p.m_name) + 1, p.m_name);
    19. }
    20. Person& operator=(Person& p)
    21. {
    22. if (this == &p)
    23. return *this;
    24. delete[]m_name;
    25. m_name = new char[strlen(p.m_name) + 1];
    26. strcpy_s(m_name, strlen(p.m_name) + 1, p.m_name);
    27. m_sex = p.m_sex;
    28. m_age = p.m_age;
    29. return *this;
    30. }
    31. void Print()
    32. {
    33. cout << m_name << " " << m_sex << " " << m_age << endl;
    34. }
    35. ~Person()
    36. {
    37. if (m_name != NULL)
    38. {
    39. delete[]m_name;
    40. m_name = NULL;
    41. }
    42. }
    43. private:
    44. char* m_name;
    45. char m_sex;
    46. int m_age;
    47. };
    48. class Student :public Person
    49. {
    50. public:
    51. Student() :m_num(0), m_score(0)
    52. {
    53. cout << "Student()" << endl;
    54. }
    55. Student(int num,const char*name,char sex,int age,int score):m_num(num),Person(name,sex,age),m_score(score)
    56. {
    57. }
    58. void Print()
    59. {
    60. cout << m_num << " ";
    61. Person::Print();
    62. cout << m_score << endl;
    63. }
    64. Student(Student& s) :Person(s), m_num(s.m_num), m_score(s.m_score)
    65. {
    66. }
    67. Student& operator=(Student& s)
    68. {
    69. if (this == &s)
    70. return *this;
    71. Person::operator=(s);
    72. m_num = s.m_num;
    73. m_score = s.m_score;
    74. return *this;
    75. }
    76. private:
    77. int m_num;
    78. int m_score;
    79. };
    80. void main()
    81. {
    82. Student s;
    83. Student s1(1001, "zhangsan", 'f', 20, 78);
    84. s.Print();
    85. s1.Print();
    86. Student s2(s1);
    87. s2.Print();
    88. s = s1;
    89. s.Print();
    90. }

    Person()                     先调用基类
    Student()                    构造s对象
    0  f 20                         没有给s对象赋值,为构造函数的默认值
    0
    1001 zhangsan f 20   打印s1对象
    78
    1001 zhangsan f 20   用s1对象拷贝构造s2对象,并将s2对象打印
    78
    1001 zhangsan f 20   将s1对象的值赋给s对象,并将s对象打印
    78

    为什么要给默认值?

    Person() :m_sex('f'), m_age(20)
        {
            m_name = new char[1];
            *m_name = '\0';
            cout << "Person()" << endl;
        }

    因为不写默认值没有指向合法的内存空间

    void main()
    {
        int* p;
        cout << p << endl;//error
    }

    7.一个类被多个类继承

    1. class Person
    2. {
    3. public:
    4. Person(int num = 1000):m_num(num)
    5. {
    6. }
    7. void print()
    8. {
    9. cout << "count = " << m_count << endl;
    10. }
    11. protected:
    12. int m_num;
    13. static int m_count;
    14. };
    15. int Person::m_count;
    16. class Student:public Person
    17. {
    18. public:
    19. Student(int num, const char*job) :Person(num)
    20. {
    21. m_job = new char[strlen(job) + 1];
    22. strcpy_s(m_job, strlen(job) + 1, job);
    23. m_count++;
    24. }
    25. private:
    26. char* m_job;
    27. };
    28. class Teacher :public Person
    29. {
    30. public:
    31. Teacher(int num, const char* job) :Person(num)
    32. {
    33. m_job = new char[strlen(job) + 1];
    34. strcpy_s(m_job, strlen(job) + 1, job);
    35. m_count++;
    36. }
    37. private:
    38. char* m_job;
    39. };
    40. class Worker :public Person
    41. {
    42. public:
    43. Worker(int num, const char* job) :Person(num)
    44. {
    45. m_job = new char[strlen(job) + 1];
    46. strcpy_s(m_job, strlen(job) + 1, job);
    47. m_count++;
    48. }
    49. private:
    50. char* m_job;
    51. };
    52. void main()
    53. {
    54. Student s(1001, "student");
    55. Teacher t(1002, "teacher");
    56. Worker w(1003, "worker");
    57. w.print();
    58. s.print();
    59. Worker w1(1006, "worker");
    60. s.print();
    61. cout << sizeof(Worker) << endl;//8
    62. }

    count = 3      static成员只构造一次
    count = 3      每构造一个继承了Person的对象,count++
    count = 4      增加了一名Worker
    8                   Person 的num+Worker的job

  • 相关阅读:
    Vue安装并使用Vue-CLI构建SPA项目并实现路由
    Spring 源码:深度解析AOP源码配置解析
    何为心理承受能力?如何提高心理承受能力?
    echarts 设置 折线图
    解决pycharm中PIL安装失败
    C++中配置json以及使用
    使用Kotlin与Unirest库抓取音频文件的技术实践
    网络编程。。
    【好书推荐】《Python编程:从入门到实践(第2版)》
    【CTA系列】Kelly公式在最优f问题上的应用
  • 原文地址:https://blog.csdn.net/m0_59052131/article/details/127928191