繼承中引數傳遞及呼叫順序

weixin_33816946發表於2016-03-08

繼承中引數傳遞及呼叫順序

一、簡單派生類的建構函式傳參

C++語言的繼承特性,指子類能夠繼承父類的屬性和行為,並能夠又一次定義或加入新的屬性和行為。

父類中為private型的屬性和行為儘管被繼承,可是子類中仍不能訪問。在繼承機制下。建構函式是不能被繼承的,所以基類建構函式的引數要由子類建構函式傳。

單一繼承的子類建構函式的宣告(.h中)形式為:

派生類建構函式名(引數總表) ();

單一繼承的子類建構函式的定義(.cpp中)形式為:

派生類名::派生類建構函式名(引數總表) : 基類建構函式名 (引數名錶)

{

派生類新增成員的初始化語句;

};  

定義派生類的建構函式時,在建構函式的引數總表中包含基類建構函式所需的引數和派生類新增的資料成員初始化所需的引數。冒號後面基類建構函式名 (引數名錶),表示要呼叫基類的建構函式。

#include "stdafx.h"

#include <iostream>    
#include <string>    
using namespace std;    

class parent
{
public:
	parent(int a,int b)  //基類建構函式,須要傳入兩個引數
	{ 
		//基類的初始化
		this->a = a;
		this->b = b;
	}
public:	
	int a,b;
};

class child:public parent
{
public:
	child(int a,int b,int c); //子類建構函式含引數總表(全部引數)
	void ShowTest()
	{
		cout<<"a = "<<a<<endl;
		cout<<"b = "<<b<<endl;
		cout<<"c = "<<c<<endl;
	}

public:
	int c;
};

//子類建構函式的定義,利用初始化表括進行引數初始化
child::child(int a,int b,int c):parent(a,b)
{
	//子類引數的初始化
	this->c = c;
}


void test()
{
	child t1(1,2,3);
	t1.ShowTest();
}

int _tmain(int argc, _TCHAR* argv[])
{
	test();
	system("pause");
	return 0;
}
測試結果:


二、複雜派生類的建構函式和解構函式

一個派生類中新新增的成員能夠是簡單的資料成員。也能夠是類物件。派生類須要初始化的資料有三部分:繼承的成員、新增類物件的成員和新增普通成員。

這樣的複雜派生類的建構函式定義例如以下:

派生類名::派生類建構函式名(總參數列) 

   :基類建構函式名1 (參數列1),

    基類建構函式名2 (參數列2),    ……

    子物件名1(參數列n),

     子物件名2(數表n+1)    ……

{

        派生類新增普通資料成員的初始化。

}

// test.cpp : 定義控制檯應用程式的入口點。
//

#include "stdafx.h"

#include <iostream>    
#include <string>    
using namespace std;    

class A
{
public:
	A(){}
	A(int i){a = i;}
	~A(){}
	void Print(){
		cout<<"a = "<<a<<endl; 
	}
	int Geta(){ return a;}
private:
	int a;
};

class B
{
public:
	B(){}
	B(int i){b = i;}
	~B(){}
	void Print(){
		cout<<"b = "<<b<<endl; 
	}
	int Getb(){ return b;}
private:
	int b;
};

class C:public A
{
public:
	C(void){}
	C(int i,int j,int k):A(i),b1(j)
	{
		c = k;
		
	}

	~C(void){}
	void Print(){
		cout<<"a = "<<Geta()<<endl; 
		cout<<"b = "<<b1.Getb()<<endl;
		cout<<"c = "<<c<<endl; 
	}
private:
	int c;
	B b1;
};

void test()
{
	C c1(1,2,3);
	c1.Print();
}

int _tmain(int argc, _TCHAR* argv[])
{
	test();
	system("pause");
	return 0;
}

測試結果:


注:在vs2010編譯環境下,若將宣告處C(void){}改為C(void);則會出現編譯錯誤:

1).obj : error LNK2019: 無法解析的外部符號 "public: __thiscall C::C(void)" (?

?0C@@QAE@XZ)。該符號在函式 "void __cdecl test(void)" (?

test@@YAXXZ) 中被引用

2)fatal error LNK1120: 1 個無法解析的外部命令

原因是另外一種方法預設僅僅宣告瞭建構函式,並沒有實現。第一種則為函式定義實現方式,儘管“;”與{}作用相似,但此處不一樣!

!!


知識點總結:

派生類建構函式的呼叫順序例如以下:

Step1:基類建構函式。

按它們在派生類定義中的先後順序,依次呼叫。

Step2:內嵌物件的建構函式。

按它們在派生類定義中的先後順序,依次呼叫。

Step3:派生類的建構函式。

   複雜派生類的解構函式,僅僅須要編寫對新增普通成員的善後處理,而對類物件和基類的善後工作是由類物件和基類的解構函式完畢的。解構函式的呼叫順序與建構函式相反。




相關文章