33 继承中的构造和析构

1 问题

  • 创建子类对象时如何初始化父类成员?父类构造函数和子类构造函数有什么关系?

2 子类对象的构造

  • 子类中可以定义构造函数

  • 子类构造函数

    • 必须对继承而来的成员进行初始化
      • 直接通过初始化列表或者赋值的方式进行初始:这种方式对于子类不能访问的父类成员不起作用,必须使用其他方法(调用父类构造函数)
      • 调用父类构造函数进行初始化
  • 父类构造函数在子类中的调用方式

    • 隐式调用(默认调用)
      • 只适用于无参构造函数使用默认参数的构造函数
    • 显式调用
      • 只能通过初始化列表进行调用
      • 适用于所有父类构造函数
  • 父类构造函数的调用

    class Child : public Parent
    {
    public:
        Child()  //隐式调用:父类无参构造函数
        {
            cout << "Child()" << endl;
        }
        Child(string s)  //显式调用:父类有参构造函数
            : Parent("Parameter to Parent")
        {
            cout << "Child() : " << s << endl;
        }
    };
    
  • 示例1:子类的构造函数1

    • Demo1:隐式调用父类无参构造函数,显式调用父类有参构造函数

      #include <iostream>
      #include <string>
      
      using namespace std;
      
      //父类
      class Parent 
      {
      public:
          //无参构造函数
          Parent()
          {
              cout << "Parent()" << endl;
          }
          //有参构造函数
          Parent(string s)
          {
              cout << "Parent(string s) : " << s << endl;
          }
      };
      
      class Child : public Parent
      {
      public:
          //隐式调用
          Child()
          {
              cout << "Child()" << endl;
          }
          //显式调用
          Child(string s) : Parent(s)
          {
              cout << "Child(string s) : " << s << endl;
          }
      };
      
      int main()
      {       
          Child c; 
          Child cc("cc");
          
          return 0;
      }
      
    • 编译运行

      Parent()
      Child()
      Parent(string s) : cc
      Child(string s) : cc
      
    • Demo2:验证隐式调用父类无参构造函数

      #include <iostream>
      #include <string>
      
      using namespace std;
      
      class Parent 
      {
      public:
          Parent(string s)
          {
              cout << "Parent(string s) : " << s << endl;
          }
      };
      
      class Child : public Parent
      {
      public:
          Child()
          {
              cout << "Child()" << endl;
          }
          Child(string s)
          {
              cout << "Child(string s) : " << s << endl;
          }
      };
      
      int main()
      {       
          Child c;  //error
          
          return 0;
      }
      
    • 编译

      test.cpp: In constructor ‘Child::Child()’:
      test.cpp:19: error: no matching function for call to ‘Parent::Parent()’
      test.cpp:9: note: candidates are: Parent::Parent(std::string)
      test.cpp:7: note:                 Parent::Parent(const Parent&)
      test.cpp: In constructor ‘Child::Child(std::string)’:
      test.cpp:23: error: no matching function for call to ‘Parent::Parent()’
      test.cpp:9: note: candidates are: Parent::Parent(std::string)
      test.cpp:7: note:                 Parent::Parent(const Parent&)
      
    • Demo3:验证隐式调用父类无参构造函数

      #include <iostream>
      #include <string>
      
      using namespace std;
      
      //父类
      class Parent 
      {
      public:
          Parent()
          {
              cout << "Parent()" << endl;
          }
          Parent(string s)
          {
              cout << "Parent(string s) : " << s << endl;
          }
      };
      
      class Child : public Parent
      {
      public:
          Child()
          {
              cout << "Child()" << endl;
          }
          Child(string s)
          {
              cout << "Child(string s) : " << s << endl;
          }
      };
      
      int main()
      {       
          Child c; 
          Child cc("cc");
          
          return 0;
      }
      
    • 编译运行

      Parent()
      Child()
      Parent()
      Child(string s) : cc
      
  • 构造规则

    • 子类对象在创建时会首先调用父类的构造函数
    • 先执行父类构造函数,再执行子类的构造函数
    • 父类构造函数可以被隐式调用或者显式调用
  • 对象创建时构造函数的调用顺序

    • 1.调用父类的构造函数
    • 2.调用成员变量的构造函数
    • 3.调用类自身的构造函数
  • 示例2:子类的构造函数2

    • Demo

      #include <iostream>
      #include <string>
      
      using namespace std;
      
      //父类
      class Object
      {
      public:
          //父类有参构造函数
          Object(string s)
          {
              cout << "Object(string s) : " << s << endl;
          }
      };
      
      //子类
      class Parent : public Object
      {
      public:
          //子类无参构造:显式调用父类有参构造函数
          Parent() : Object("Default")
          {
              cout << "Parent()" << endl;
          }
          //子类有参构造:显式调用父类有参构造函数
          Parent(string s) : Object(s)
          {
              cout << "Parent(string s) : " << s << endl;
          }
      };
      
      //子类
      class Child : public Parent
      {
          //组合关系
          Object mO1;
          Object mO2;
      public:
          Child() : mO1("Default 1"), mO2("Default 2")
          {
              cout << "Child()" << endl;
          }
          //先父类,再成员变量
          Child(string s) : Parent(s), mO1(s + " 1"), mO2(s + " 2")
          {
              cout << "Child(string s) : " << s << endl;
          }
      };
      
      int main()
      {       
          Child cc("cc");
          
          return 0;
      }
      
    • 编译运行

      Object(string s) : cc
      Parent(string s) : cc
      Object(string s) : cc 1
      Object(string s) : cc 2
      Child(string s) : cc
      

3 子类对象的析构

  • 析构函数的调用顺序与构造函数相反

    • 1.执行自身的析构函数
    • 2.执行成员变量的析构函数
    • 3.执行父类的析构函数
  • 示例:对象的析构

    • Demo

      #include <iostream>
      #include <string>
      
      using namespace std;
      
      class Object
      {
          string ms;
      public:
          Object(string s)
          {
              cout << "Object(string s) : " << s << endl;
              ms = s;
          }
          ~Object()
          {
              cout << "~Object() : " << ms << endl;
          }
      };
      
      class Parent : public Object
      {
          string ms;
      public:
          Parent() : Object("Default")
          {
              cout << "Parent()" << endl;
              ms = "Default";
          }
          Parent(string s) : Object(s)
          {
              cout << "Parent(string s) : " << s << endl;
              ms = s;
          }
          ~Parent()
          {
              cout << "~Parent() : " << ms << endl;
          }
      };
      
      class Child : public Parent
      {
          Object mO1;
          Object mO2;
          string ms;
      public:
          Child() : mO1("Default 1"), mO2("Default 2")
          {
              cout << "Child()" << endl;
              ms = "Default";
          }
          Child(string s) : Parent(s), mO1(s + " 1"), mO2(s + " 2")
          {
              cout << "Child(string s) : " << s << endl;
              ms = s;
          }
          ~Child()
          {
              cout << "~Child() " << ms << endl;
          }
      };
      
      int main()
      {       
          Child cc("cc");
          
          cout << endl;
          
          return 0;
      }
      
    • 编译运行

      Object(string s) : cc
      Parent(string s) : cc
      Object(string s) : cc 1
      Object(string s) : cc 2
      Child(string s) : cc
      
      ~Child() cc
      ~Object() : cc 2
      ~Object() : cc 1
      ~Parent() : cc
      ~Object() : cc
      
posted @ 2020-10-30 19:38  nxgy  阅读(70)  评论(0编辑  收藏  举报