继承中的构造和析构

子类的构造函数必须对继承而来的成员进行初始化
1.直接通过初始化列表或者赋值的方式进行初始
2.调用父类构造函数进行初始化
父类构造函数在子类中的调用方式
1.默认调用.适用无参构造函数和使用默认参数的构造函数
2.显示调用.通过初始化列表进行调用,适用于所有父类的构造函数
例子:

class Child : public parent
{
  public:
  Child()/*隐式调用,调用父类无参构造函数和默认参数的构造函数,如果父类没有该类型的构造函数则报错*/
  {
   cout<<"Child()"<<endl;
  }
  Child(string s) : Parent("Parameter to Parent")/*显示调用,通过初始化列表进行调用*/
 {
    cout<<"Child(): "<<s<<endl;
 }
}

看下面这个例子:

#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 : Parent
{
  public:
  Child()
  {
     cout << "Child()"  <<endl;
  }
  Child(string s)
  {
    cout<<"Child(string s): "<<s<<endl;
  }
};
int main()
{
   Child c;
   Child c1("c1");
   return 0;
}

结果:

Parent ()
Child()
Parent ()
Child(string s): c1

因为Child c,Child c1(“c1”)都是隐式调用,调用父类无参构造函数或者默认参数的构造函数,而父类中只有Parent()这个无参构造函数,所以先调用父类的无参构造函数再调用本类的构造函数
代码改动:

class Child : Parent
{
  public:
  Child()
  {
     cout << "Child()"  <<endl;
  }
  Child(string s) : Parent(s)
  {
    cout<<"Child(string s): "<<s<<endl;
  }
};

结果:

sice@sice:~$ ./a.out 
Parent ()
Child()
Parent(string s)c1
Child(string s): c1

现在 Child c1(“c1”)成了显示调用,所以调用了父类的参数一致的构造函数,现在我们可以得出一套构造规则
构造规则:
子类对象在创建时会首先调用父类的构造函数
先执行父类构造函数再执行子类的构造函数
父类构造函数可以被隐式调用或者显示调用

补充:对象创建时构造函数的调用顺序
1.调用父类的构造函数
2.调用成员变量的构造函数
3.调用类自身的构造函数
例子:

#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 c;
   Child c1("c1");
   return 0;
}

结果:

sice@sice:~$ ./a.out 
Object (string s)c1
Parent(string s)c1
Object (string s)c11
Object (string s)c12
Child(string s): c1

可以看出父类的调用最先,就是Parent的构造函数,接着"客人"mO1(s + “1”),mO2( s + “2”),最后是自己的构造函数

析构函数的调用顺序与构造函数相反
1.执行自身的析构函数
2.执行成员变量的析构函数
3.执行父类的析构函数
例子:

#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

可以看出析构顺序与构造顺序对称相反

要点:
子类对象在创建的时候需要调用父类构造函数进行初始化
先执行父类构造函数然后执行成员的构造函数
!!父类构造函数显示调用需要在初始化列表中进行!!
子类对象在销毁时需要调用父类析构函数进行清理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值