(c++)4.5继承机制下的构造函数与析构函数

注意啦,在派生类的生成过程中,派生类继承基类的大部分成员,但是!!!不继承基类的构造函数(包括拷贝构造函数)和析构函数【所以需要自己手动添加啦】

4.5.1继承机制下构造函数的调用顺序(告诉你咋继承基类的构造函数)

方法:在定义派生类的构造函数时,除了对自己数据成员进行初始化外,还要调用基类的构造函数来初始化基类数据成员。
格式就不给啦,感觉有点抽象记不住。。。。直接上例子吧(对了这还分单继承和双继承)

单继承机制下构造函数的调用顺序

#include<iostream>
using namespace std;
class Baseclass
{
	public:
		Baseclass(int i)
		{
			a=i;
			cout<<"constructing Baseclass a="<<a<<endl;
		}
		private:
			int a;
};
class Derivedclass:public Baseclass
{
	public:
		Derivedclass(int i,int j);
	private:
		int b;
};
Derivedclass::Derivedclass(int i,int j):Baseclass(i)//派生类的构造函数
{
	b=j;
	cout<<"constructing Derivedclass b="<<b<<endl;
}
int main()
{
	Derivedclass x(5,6);
	return 0;
}

结果

constructing Baseclass a=5
constructing Derivedclass b=6

当说明派生类的一个对象时,首先基类构造函数被调用,子对象所在类构造函数次之,最后执行派生类构造函数

//包括子对象时,构造函数的调用顺序
#include<iostream>
using namespace std;
class Base1//基类
{
	public:
		Base1(int i)
		{
			a=i;
			cout<<"constructing Base1 a="<<a<<endl;
		}
	private:
		int a;
};
class Base2
{
	public:
		Base2(int i)
		{
			b=i;
			cout<<"constructing Base2 b="<<b<<endl;
		}
	private:
		int b;
 };
 class Base3
 {
 	public:
 		Base3(int i)
 		{
 			c=i;
 			cout<<"constructing Base3 c="<<c<<endl;
		}
	private:
		int c;
 };
 class Derivedclass:public Base1//派生类
 {
 	public:
 		Derivedclass(int i,int j,int k,int m);
 	private:
 		int d;
 		Base2 f;
 		Base3 g;
  };
  Derivedclass::Derivedclass(int i,int j,int k,int m):Base1(i),g(j),f(k)
  {
  	d=m;
  	cout<<"constructing Derivedclass d="<<d<<endl;
  }
  int main()
  {
  	Derivedclass x(5,6,7,8);
  	return 0;
  }
  

结果:

constructing Base1 a=5
constructing Base2 b=7
constructing Base3 c=6
constructing Derivedclass d=8

注意:当建立Derivedclass类对象x时,首先调用基类Base1的构造函数,然后分别调用子对象所在类的构造函数(子对象的调用顺序取决于它们在派生类中被说明的顺序,与它们在成员初始化列表中的顺序无关)

多继承机制下构造函数的调用顺序

顺序:

  • 先调用所有基类的构造函数
  • 再调用派生类中子对象类的构造函数
  • 最后调用派生类的构造函数
  • 处于同一层次的各基类构造函数的调用顺序取决于定义派生类所指定的基类顺序(等会我在程序里面标一下就清楚是哪了)
    上例子!
#include<iostream>
using namespace std;
class Base1//基类
{
	public:
		Base1(int i)//基类构造函数 
		{
			a=i;
			cout<<"constructing Base1 a="<<a<<endl;
		}
	private:
		int a;
};
class Base2//基类 
{
	public:
		Base2(int i)//基类构造函数 
		{
			b=i;
			cout<<"constructing Base2 b="<<b<<endl;
		}
	private:
		int b;
 };
 class Derivedclass:public Base1,public Base2//派生类(就是这里的顺序!!!)
 {
 	public:
 		Derivedclass(int i,int j,int k);
 	private:
 		int d;
  };
  Derivedclass::Derivedclass(int i,int j,int k):Base2(i),Base1(j) 
  {
  	d=k;
  	cout<<"constructing Derivedclass d="<<d<<endl;
  }
  int main()
  {
  	Derivedclass x(5,6,7);
  	return 0;
  } 

结果:

constructing Base1 a=5
constructing Base2 b=7
constructing Base3 c=6
constructing Derivedclass d=8

如果派生类有一个虚基类作为祖先类,那么在派生类构造函数的初始化列表中需要做出对虚基类构造函数的调用,如果没列出则表明调用的是虚基类的无参数构造函数。不管初始化列表中次序如何,对虚基类构造函数的调用总是先于普通基类的构造函数。

//有虚基类时,多继承下构造函数的调用顺序
#include<iostream>
using namespace std;
class Base1//基类
{
	public:
		Base1()//基类构造函数 
		{
			cout<<"constructing Base1 "<<endl;
		}
};
class Base2//基类 
{
	public:
		Base2()//基类构造函数 
		{
			cout<<"constructing Base2 "<<endl;
		}
 };
 class Derived1:public Base2,virtual public Base1 
 {
 	public:
 		Derived1()
 		{
 			cout<<"constructing Derived1"<<endl;
 		}
  };
 class Derived2:public Base2,virtual public Base1 
 {
 	public:
 		Derived2()
 		{
 			cout<<"constructing Derived2"<<endl;
		 }
  };
   class Derived3:public Derived1,virtual public Derived2
 {
 	public:
 		Derived3()
 		{
 			cout<<"constructing Derived3"<<endl;
		 }
  };
  int main()
  {
  	Derived3 obj;
  	return 0;
  }
  

结果:

constructing Base1
constructing Base2
constructing Derived2
constructing Base2
constructing Derived1
constructing Derived3

4.5.2派生类构造函数的规则

在基类中定义有默认构造函数或者没有定义任何构造函数时,派生类构造函数中可以省略对基类的调用,这就是隐式调用。
下面分几种情况来讨论派生类构造函数的规则

派生类有构造函数,基类没有

当创建派生类对象时,派生类相应的构造函数会被自动调用。

#include<iostream>
using namespace std;
class Baseclass
{
	private:
		int a;
};
class Derivedclass:public Baseclass
{
	public:
		Derivedclass();
		Derivedclass(int i);
	private:
		int b;
};
Derivedclass::Derivedclass()
{
	cout<<"construcing constructor Derviedclass"<<endl;
}
Derivedclass::Derivedclass(int i)
{
	b=i;
	cout<<"construcing constructor Derviedclass b="<<b<<endl;
}
  int main()
  {
  	Derivedclass x1(5);
  	Derivedclass x2;
  	return 0;
  }

派生类没有构造函数,基类有(基类必须拥有默认构造函数!)

#include<iostream>
using namespace std;
class Baseclass
{
	public:
		Baseclass()//不能不定义 
		{
			cout<<"construcing constructor Baseclass"<<endl;
		}
		Baseclass(int i)//可以不要,反正啥用也没有 
		{
			a=i;
			cout<<"construcing constructor Baseclass a="<<a<<endl;
		}
	private:
		int a;
};
class Derivedclass:public Baseclass
{
	private:
		int b;
};
  int main()
  {
  	Derivedclass x;
  	return 0;
  }
  

派生类有构造函数,基类有默认构造函数

那么创建派生类的对象时,基类的默认构造函数会自动调用,除非当前被调用的派生类构造函数在其初始化列表中显式调用了基类的有参构造函数

#include <iostream>
using namespace std;
class Baseclass            //基类 
{ 
    public:
        Baseclass()         //缺省构造函数
		{
            cout<<"default constructor Baseclass"<<endl;  
		}	 
        Baseclass(int i)    //有参构造函数
		{
		    a=i;
            cout<<"constructing Baseclass a="<<a<<endl;
        } 
	private:
        int a;	
};
class Derivedclass:public Baseclass   //派生类 
{
    public:
        Derivedclass(int i);     
		Derivedclass(int i,int j);
    private:
        int b;
};  
Derivedclass::Derivedclass(int i)        //调用基类缺省构造函数
{ 
	b=i;
    cout<<"constructing Derivedclass b="<<b<<endl;
} 
Derivedclass::Derivedclass(int i,int j):Baseclass(i)     //调用基类有参构造函数
{ 
	b=j;
    cout<<"constructing Derivedclass b="<<b<<endl;
}
int main()
{ 
    Derivedclass x1(5,6);   //创建派生类对象x1,调用Derivedclass类的有两个参数的构造函数,
	                        //初始化列表中显示调用了Baseclass的有参构造函数,
    Derivedclass x2(7);     //建派生类对象x2,调用Derivedclass类的有一个参数的构造函数,
                            //由于没有显示调用基类的构造函数,所以基类的默认构造函数被调用 
	return 0;
}

派生类和基类都要构造函数,但是基类没有默认构造函数

//基类无缺省构造函数时,派生类构造函数的规则。
#include <iostream>
using namespace std;
class Baseclass     //基类,没有默认构造函数 
{ 
   public:
        //Baseclass(){  }
		Baseclass(int i)     //构造函数 
		{
		    a=i;
            cout<<"constructing Baseclass a="<<a<<endl;
		}
	private:
        int a;	 
};
class Derivedclass:public Baseclass   //派生类 
{
    public:
        Derivedclass(int i);
        Derivedclass(int i,int j);
    private:
        int b;
};  
Derivedclass::Derivedclass(int i):Baseclass(0)     //错误,因没有显式调用基类构造函数
{ 
    b=i;
    cout<<"constructing Derivedclass b="<<b<<endl;
} 
Derivedclass::Derivedclass(int i,int j):Baseclass(i)
{ 
    b=j;
    cout<<"constructing Derivedclass b="<<b<<endl;
}
int main()
{ 
    Derivedclass x1(5,6);
    Derivedclass x2(7);
	return 0;
}

那么派生类的每一个构造函数必须在其初始化列表中显式调用基类的某个构造函数

4.5.3继承机制下析构函数的调用顺序

由于析构函数也不能被继承,因此在执行派生类的析构函数时,也要调用基类的析构函数,执行顺序如下:

  • 先调用派生类的析构函数
  • 再调用派生类中子对象类的析构函数
  • 再调用普通类的析构函数
  • 最后调用虚基类的析构函数
    (与执行析构函数的顺序相反)
//派生类析构函数的调用顺序。
#include <iostream>
using namespace std;
class Base1            //基类
{ 
    public:
        Base1(int i)    //基类构造函数
		{
		    a=i;
            cout<<"constructing Base1 a=" <<a<<endl;
		}
		~ Base1()       //基类析构函数
		{
		    cout<<"destructing Base1"<<endl;
		}
    private:
        int a;
};
class Base2           //子对象f所属类
{ 
   public:
        Base2(int i)   //构造函数
		{
			b=i;
            cout<<"constructing Base2 b=" <<b<<endl;
		}
		~Base2()      //析构函数
		{
            cout<<"destructing Base2"<<endl;
		}
    private:
        int b;		
};
class Base3              //子对象g所属类
{ 
    public:
        Base3(int i)     //构造函数
		{
			c=i;
            cout<<"constructing Base3 c=" <<c<<endl;
		}
		~Base3()//析构函数
		{
		    cout<<"destructing Base3"<<endl;
		}
    private:
        int c;
};
class Derivedclass:public Base1        //派生类
{
    public:
        Derivedclass(int i,int j,int k,int m);
        ~Derivedclass();
    private:
        int d;
		Base2 f;    //子对象f 
		Base3 g;    //子对象g 
};  
Derivedclass::Derivedclass(int i,int j,int k,int m):Base1(i),g(j),f(k)
//派生类构造函数
{ 
	d=m;
    cout<<"constructing Derivedclass d="<<d<<endl;
}
Derivedclass::~Derivedclass()      //派生类析构函数
{
    cout<<"destructing Derivedclass"<<endl;
}

int main()
{ 
    Derivedclass x(5,6,7,8);
	return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值