C++ Inheritance Constructor

C++ Inheritance Constructor: जैसाकि आपने देखा कि Constructors Special प्रकार के function होते हैं। ये Inheritance में एक असाधारण Role Play करते हैं। इसलिए हमें ये समझना जरूरी है कि हमें Constructors की जरूरत कब होती है और कब नहीं। साथ ही हमें ये भी पता होना चाहिए कि एक Constructor किस प्रकार से दूसरे Constructor को एक Special Syntax द्वारा Call कर सकता है।   

Chain of Constructors

जब हम किसी Derive Class के Object को Define करते हैं तब Derive Class के Constructor के  Execution के साथ ही Base Class के Constructor का भी Execution होता है। वास्तव में Base Class के Constructor का Execution पहले होता है और फिर Derive Class के Constructor का Execution होता है।  जैसाकि एक सामान्‍य नियम है कि यदि हमें कोई बडी चीज बनानी होती है तो सीधे ही हम उस बडी चीज को नहीं बना सकते हैं। बल्कि पहले हम उस बडी चीज के छोटे-छोटे हिस्से या Parts बनाते हैं।

उदाहरण के लिए मानलो कि एक Computer बनाना है। क्या सीधे ही एक बार में Computer तैयार हो जाता है।

नहीं!

पहले Computer के सभी जरूरी हिस्से या Parts जैसे कि Monitor, Processor, motherboard, Speakers, RAM, Hard Disk आदि बनाए जाते हैं और जब सभी हिस्से तैयार हो जाते हैं, तब अन्त में सभी हिस्सों को जोडने से पूरा Computer बन जाता है यानी Assemble हो जाता है।

ठीक इसी प्रकार से Base Class का जो Object होता है वह Derived Class के Object का एक Sub-Object यानी एक हिस्सा या Part होता है और पहले इस हिस्से को ही बनाना (Construct करना) पडता है।

सारांश में कहें तो Base Class व Derived Class के बीच भी एक Relationship होती है, जिसे “Part of” Relationship कहा जाता है।

उदाहरण के लिए मानलो कि हम एक Computer Class बनाते हैं, तो Computer Class के कई अन्‍य Objects जैसे कि CPU, RAM, Hard Disk आदि से बना हुआ होता है। इस स्थिति में हम कह सकते हैं कि RAM Computer System का एक Part है। यानी:

RAM is a “Part of” Computer
CPU is a “Part of” Computer

यदि एक Line में इस सम्बंध को Computer की Logically Class के लिए परिभाषित करें, तो हम कह सकते हैं कि Base Class Derived Class का एक Part होता है। यानी

Base Class is a “Part of” Derived Class

क्योंकि Base Class के सारे गुण Derived Class में होने के साथ-साथ Derived Class के स्वयं के कुछ गुण भी होते हैं, जो Base Class में नहीं होते हैं। यानी Derived Class Base Class की तुलना में अधिक Heavy हो जाती है। इसलिए Base Class Derived Class का एक हिस्सा मात्र बन जाता है।

इसीलिए Derived Class का कोई Object Create करने पर सबसे पहले Base Class का Constructor Execute होता है और चूंकि हम “C++” में Multiple Classes के Features को नई Class में Derive कर सकते हैं और किसी Derived Class के गुणों को वापस से किसी और Derive Class में Inherit कर सकते हैं, इसलिए Base Class के Constructor के Execute होने के बाद क्रम से विभिन्न Derived Class के Constructor Execute होते हैं।

हमारे इस उदाहरण के आधार पर कहें तो इस उदाहरण में केवल दो Classes एक Base Class व दूसरी Derived Class है, इसलिए इसमें पहले Base Class का Constructor Execute होता है फिर Derived Class का। जैसाकि हमने Computer Class का उदाहरण लिया है। तो एक Computer Object का Contractor Execute होने से पहले उसके सभी अन्‍य Sub-Objects के Constructor पहले Execute होते हैं और अन्त में Computer Class का Constructor Execute होता है। चलिए, इस तथ्य को निम्न Program द्वारा Demonstrate करते हैं:

// Program
// tests constructors and destructors in inheritance
#include <iostream.h>
class Parent
{
	public:
		Parent()
		{ 
			cout << "\n   Parent constructor"; 
		}

		~Parent()
		{ 
			cout << "\n   Parent destructor"; 
		}
};

class Child : public Parent
{
	public:
		Child()
		{
			cout << "\n   Child constructor"; 
		}

		~Child()
		{
			cout << "\n   Child destructor"; 
		}
};

void main()
{
	cout << "\nStarting";
	Child ch;                 // create a Child object
	cout << "\nTerminating";
}

इस Program में एक Parent Class है और इस Parent Class से Derive की गई एक Child Class है। main() Function में ये Program Child Class का एक Object Create करता है। हमने इस Program में Constructors व Destructors को उनके दृश्‍य रूप (Explicit Form) में Create किया है, ताकि ये जान सकें कि Base Class व Child Class के Constructors व Destructors किस प्रकार से व कब Executes होते हैं। इस Program का Output हमें निम्नानुसार प्राप्त होता है:

Starting
   Parent Constructor
   Child Constructor
Terminating
   Child destructor
   Parent destructor

हम इस Output में देख सकते हैं, कि base Class का Constructor पहले Execute होता है। उसके बाद Derived Class का Constructor Execute होता है। जब Program Terminate होता है तब Destructors Reveres Order में Execute होते हैं। यानी पहले Derived Class का Object Destroy होता है और बाद में Base Class का।

आप सोच सकते हैं कि हमने Object तो केवल एक ही Create किया है फिर यहां दो Class के Object कैसे Destroy हो रहे हैं। वास्तव में Object एक ही Create होता है, लेकिन चूंकि Derived Class किसी Base Class से Inherit होता है, इसलिए कोई Derive Class जितनी अन्‍य Classes से Inherit होता है, Logically उतने ही Objects Compiler में Internally Create होते हैं। Compiler स्वयं ही इन विभिन्न Constructors व Destructors को Automatically Call करता है। एक Class Use करने वाले Programmer को इनके बारे में सोचने की जरूरत नहीं होती है।

हालांकि हमने इस Program में दृश्‍य रूप (Explicit Form) में Constructors व Destructors को Represent किया है, जबकि Compiler सभी अन्‍य Programs में इन्हें अदृश्‍य रूप (Implicit Form OR Invisibly ) में इन्हें Object या Subobject के Create या Destroy होने पर Call करता है। एक Class User को हमेंशा इस बात को ध्‍यान में रखना चाहिए कि वह चाहे Constructors व Destructors को Define करे या ना करे, लेकिन Invisible Form में ये Object व Sub-object के Create व Destroy होने पर Execute होते ही हैं।

वास्तव में एक Object का Compiler द्वारा प्रदान किया अदृश्‍य (Implicit) Constructor Programmer द्वारा Create किए गए दृश्‍य (Explicit) Constructor से हमेंशा पहले Execute होता है। जब Programmer का Constructor Execute होना शुरू करता है तब तक Programmer के सभी Objects व Subobject पूरी तरह से Create व Initialize हो चुके होते हैं।

No Argument Inheritance Constructor

हम तब तक किसी Derived Class में कुछ Argument वाले Constructors को Use नहीं कर सकते हैं, जब तक कि उस Derived Class के Base Class में Explicitly उतने ही Argument वाला Constructor Define ना किया गया हो। यानी यदि Base Class में n-Argument का Constructor हो तो Derived Class में भी n-Arguments का Constructor Defined किया जाना जरूरी होता है। इस प्रक्रिया को समझने के लिए निम्न Program देखिए:

class Mu                      		// base class
{
	private:
		int mudata;             // data

	public:
		Mu() : mudata(0)        // no-arg constructor
		{  }

		Mu(int m) : mudata(m)   // one-arg constructor
		{  }
};

class Nu : public Mu          	// derived class
{                          	// no constructors
};

void main()
{
	Nu n1;       		// can use the no-arg constructor in Mu
	// Nu n2(177);  	// error: cannot use one-arg constructor
}

इस उदाहरण में हम Class Nu जो कि Class Mu से Derived है, की Specification को बिना Specification के लिख सकते हैं। इस Nu Derived Class के लिए Compiler किसी प्रकार का Error Generate नहीं करता है। इसी तरह से हम Class Nu का बिना Argument वाला Object भी Create कर सकते हैं, जिस तरह से main() function के पहले Statement में किया गया है।  लेकिन हम Nu Class का एक ऐसा Object Create नहीं कर सकते हैं जो Argument लेता हो। यानी यदि हम main() Function के दूसरे Statement जिसे Comment बनाया गया है, यदि उसे एक Normal Statement बना कर Program को Recompile करें, तो Compiler निम्नानुसार एक Error Generate करता है:

Could not find a match for ‘Nu::Nu(int)’

Arguments Inheritance Constructor

यदि हम Derived Class Nu में एक Explicit 1-Argument Constructor Add करते हैं, तो हमें इसमें ठीक उसी प्रकार से जिस प्रकार से हम किसी भी Class के साथ करते हैं, एक No-Argument Constructor भी Add करना जरूरी होता है। इसे समझने के लिए पिछले Program में ही थोडा सा परिवर्तन किया गया है। Modified Program निम्नानुसार है:

class Mu                      	// base class
{
	private:
		int mudata;             // data

	public:
		Mu() : mudata(0)        // no-arg constructor
		{  }

		Mu(int m) : mudata(m)   // one-arg constructor
		{  }
};

class Nu : public Mu
{
	public:
		Nu()                     // no-arg constructor
		{  }

		Nu(int n) : Mu(n)        // one-arg constructor
		{  }
};

void main()
{
	Nu n1;       	// can use the no-arg constructor in Mu
	Nu n2(177);  
}

अब हम main() function के दूसरे Statement को Comment से Normal Statement में Convert कर सकते हैं। अब Compiler इस Program को बिना किसी प्रकार की Error दि, हुए Normally Execute करता है।  इस Program में जब हम Nu Class का Object Create करते हैं और उसे एक Argument Pass करते हैं तो ये Argument एक नए Syntax द्वारा Derived Class से Base Class के Constructor को Execute करता है। Derived Class का Constructor Nu(int) Base Class के Constructor Mu(int) को निम्न Syntax के Statement द्वारा Call करता है:

Nu(int n) : Mu(n)              // 1-Argument Constructor
{ }

इस Statement में Colon के बाद जो कुछ भी लिखा गया है, वह Initializer List है, जहां Constructor के Execute होने से पहले Data Initialize हो जाते हैं। ये Syntax उसी प्रकार का है जिस प्रकार से हम किसी Constructors को Use करके Object के विभिन्न Basic Data Type के Data Item या Instance Variables को Initialize करते हैं।  लेकिन यहां पर ये Syntax एक Constructor को Call करता है। वास्तव में ये Operations Theoretically समान हैं। यानी प्रथम स्थिति में एक Class के किसी Object को Initialize किया जाता है, जबकि दूसरी स्थिति में एक Basic प्रकार के Variable को Initialize किया जाता है। लेकिन “C++” Objects व Basic Data Types के Variables, दोनों के साथ समान प्रकार से Treat करता है।

इस Program में Derive Class का Constructor Argument n को Base Class के Constructor में Pass करता है। ये स्वयं कोई काम नहीं करता है इसलिए इसके Braces को Empty रखा गया है। ये Derive Class की एक Common Situation है: Constructor की function Body को Empty रखा जाता है क्योंकि इसका सारा काम Initialization list द्वारा होता है।  इस Program में Base Class में no-argument व one-argument Constructor है, इसलिए हमें Derive Class में भी no-argument व one-argument के दो Constructor लिखने पडे हैं।

ध्‍यान से देखें तो पता चलेगा कि No-Argument Constructor को तो दोनो Class में समान तरीके से लिखा गया है, लेकिन One-Argument Constructor को Derive Class में लिखने का तरीका थोडा अलग है।  Nu(int n) : Mu(n) Statement Object Creation के समय एक मान प्राप्त करता है और वह मान Constructor में int n Argument को भेज देता है। Variable n का ये मान Mu Class को Pass होता है और Mu Class में n का मान Mu Class के One-Argument Constructor के Variable int m को प्राप्त हो जाता है।  जिससे Base Class का One-Argument Constructor Execute होता है और m का मान Base Class के Data Member mudata को प्राप्त हो जाता है। इस प्रकार से Inheritance में Derive Class से Base Class में Constructor द्वारा मान Data Member को Initialize हो जाता है।   

Adding Functionality to the Derived Class Constructor

सभी Derive Class Constructor की Function Body को Empty नहीं रखा जाता है। मान लो कि हम TTime Class में Extra Functionality Add करना चाहते हैं। हम चाहते हैं कि User Hours व Minutes के मान को उसकी Limit से अधिक मान प्रदान ना कर सके। यानी Hours 23 से व Minutes 59 से अधिक Initialize ना किया जा सके।  यदि User Limit को पार करता है, तो Constructor द्वारा एक Error Message आना चाहिए। Class में इस नए Feature को Add करने के लिए हम TTime2 नाम की एक नई Class Derive करते हैं, जो कि इस Error को Check करता है। इसका Program निम्नानुसार है:

// Constructors and inheritance in the TTime Class
#include <iostream.h>
#include <process.h>        	// for exit()
class TTime
{
	protected:
		int hours;            	// 0 to 23
		int minutes;          	// 0 to 59

	public:
		// no-arg Constructor
		TTime() : hours(0), minutes(0)
		{  }

		// two-arg Constructor
		TTime(int h, int m) : hours(h), minutes(m)
		{  }

		void display() const  	// output to screen
		{ 
			cout << hours << ':' << minutes; 
		}
};  // end class TTime

class TTime2 : public TTime
{
	public:                  	
		// no-arg Constructor
		TTime2() : TTime()
		{  }               

		// two-arg Constructor
		TTime2(int h, int m) : TTime(h, m)
		{
			if(minutes>59 || hours>23)
			{
				cout << "\nError: invalid TTime value "
				<< hours << ':' << minutes; 
				exit(-1); 
			}
		}
};  // end Class TTime2

void main()
{
	TTime2 Time0;            	// ok (no-arg Constructor)
	cout << "\n Time0 = ";
	Time0.display();

	TTime2 Time1(10, 45);    	// ok (2-arg Constructor)
	cout << "\nTime1 = ";
	Time1.display();

	TTime2 Time2(10, 65);    	// User error (2-arg Constructor)
	cout << "\nTime2 = ";
	Time2.display();
}

TTime2 Class में हमने एक no-Argument Constructor व एक 2-Argument Constructor Create किया है। 2-Argument Constructor Base Class के 2-argument Constructor को Call करता है और ये Check करता है कि Input किया गया मान Limit से अधिक है या नहीं।  Derive Class के Object में यदि Initialize किया जाने वाला मान यानी घण्‍टा या मिनट क्रमश: 23 या 59 से अधिक है, तो Constructor हमें एक Error Massage देता है और हमें Program से बाहर निकाल देता है।

main() Program में TTime2 Class के तीन Objects Create किए गए हैं। पहला no-argument Constructor को Use करता है, दूसरा 2-Argument Constructor को Appropriate Argument Value के साथ Use करता है, और तीसरा 2-Argument Constructor को एक Out Of Limit संख्‍या के मान के Minutes के साथ Use करता है। इस Program का Output निम्नानुसार आता है:

Time0 = 0:00
Time1 = 10:45
Error: invalid TTime value 10:65

ये Error Massage का Statement हमने Constructor में ही लिख दिया है, जिससे जैसे ही Object Creation के समय गलत मान Initialize किया जाता है, ये Error Massage Execute हो जाता है। (C++ Inheritance Constructor – StackOverflow)

CPP Programming Language in Hindiये Article इस वेबसाईट पर Selling हेतु उपलब्‍ध EBook C++ Programming Language in Hindi से लिया गया है। इसलिए यदि ये Article आपके लिए उपयोगी रहा, तो निश्चित रूप से ये पुस्तक भी आपके लिए काफी उपयोगी साबित होगी। 

C++ Programming Language in Hindi | Page: 666 | Format: PDF

BUY NOW GET DEMO REVIEWS