Arrays of Pointers to Objects – Virtual Functions

Arrays of Pointers to Objects: Virtual Functions को Use करने का सबसे Common तरीका “Array of Pointers to Objects” है। निम्न उदाहरण Program में हमने पिछले उदाहरण की Classes का ही प्रयोग किया है। केवल main() Function में ही कुछ परिवर्तन किया है। Program निम्नानुसार है:

		// Array of Pointers to Objects with Virtual Functions
		#include <iostream.h>
		#include <conio.h>

		class BaseClass                        	// base class
		{
			public:
				virtual void show()         	// virtual function
				{ cout << "\nBase"; }
		};

		class DerivedClass1 : public Base         	// derived class 1
		{
			public:
				void show()
				{ cout << "\nDerivedClass1"; }
		};

		class DerivedClass2 : public Base         	// derived class 2
		{
			public:
				void show()
				{ cout << "\nDerivedClass2"; }
		};

		void main()
		{
			Base* arrayBase[2];              	// array of pointers to Base
			DerivedClass1 dv1;               	// object of derived class 1
			DerivedClass2 dv2;               	// object of derived class 2

			arrayBase[0] = &dv1;             	// put address of dv1 in array
			arrayBase[1] = &dv2;             	// put address of dv2 in array

			for(int j=0; j<2; j++)           	// for all array elements,
			arrayBase[j]->show();         	//   execute show()
			getch();
		}

हमने Objects dv1 व dv2 के Addresses को arrayBase नाम के Array में Store कर दिया है जो कि BaseClass Type के प्रकार का एक Array है। दूसरे उदाहरण की तरह Compiler show() Function को Call करने के लिए Array में Stored Objects के Pointers का प्रयोग करता है ना कि Array का। इस Program का Output भी पिछले उदाहरण Program की तरह निम्नानुसार ही प्राप्त होता है:

// Output
   DerivedClass1
   DerivedClass2

main() Function में हम देख सकते हैं कि कितनी आसानी से Object के प्रकार के आधार पर हम एक ही show() Function को Call करने वाले Statement से विभिन्न show() Functions को Invoke कर सकते हैं।

एक बात हमेंशा ध्‍यान रखें कि Virtual Functions का Mechanism केवल Pointers to Objects या References पर काम करता है, Objects पर नहीं। यानी यदि हम main() Function को निम्नानुसार Objects का Array बनाकर Execute नहीं कर सकते हैं:

	void main()
	{
		Base arrObjs[2];              	// array holds base class objects
		DerivedClass1 dv1;            	// object of derived class 1
		DerivedClass2 dv2;            	// object of derived class 2

		arrObjs[0] = dv1;             	// put dv1 object in array
		arrObjs[1] = dv2;             	// put dv2 object in array

		for(j=0; j<2; j++)            	// for all array elements,
			arrObjs[j].show();         	//    execute show()
		getch();
	}

हालांकि Compiler हमें ये सुविधा देता है कि हम Base Class के Array में Derived Class के Objects को Store कर सकते हैं, लेकिन इस स्थिति में हमें वह परिणाम प्राप्त नहीं होता है जो हम चाहते हैं। main() Function के इस Version को Execute करने पर हमें निम्नानुसार Output प्राप्त होता है:

// Output
   DerivedClass1
   DerivedClass2

आप पूंछ सकते हैं कि इस main() Function से Derived Classes के show() Functions Execute क्यों नहीं हुए ?

इसका कारण ये है कि Base Class के Object व Derived Class के Object की Size समान नहीं होती है। Derived Class के Objects सामान्‍यतया Base Class के Objects से बडे होते हैं, हालांकि हमारे इस उदाहरण में ऐसा नहीं हुआ है, क्योंकि Derived Class में Additional Data होते हैं जो कि उन्हें Base Class के प्रकार का (Kind of) बनाते हैं। परिणामस्वरूप Derived Class के Objects Base Class के Array में Fit नहीं हो पाते हैं।

यदि हम Base Class Array में Derived Class Objects को Store करते हैं, तो Derived Class Objects के टुकडे हो जाते हैं। लेकिन जब हम Base Class Array में Derived Class के Objects के Pointers को Store करते हैं, तब ऐसा नहीं होता है।

सारांश ये है कि Derived Class Objects को कभी भी Base Class के Array में Store नहीं करना चाहिए। इससे Object की Information का Loss हो जाएगा और Derived Class के Objects ये भूल जाएंगे कि वे किस Class के Objects हैं।

जब हम Pointers की बात करते हैं तब हमेंशा Base Class व Derived Class Pointers समान Size के होते हैं, इसलिए Object के किसी Information का Loss नहीं होता है। सारांश ये है कि जब Polymorphism का प्रयोग किया जा रहा हो तब Virtual Functions को Invoke करने के लिए Objects के Pointers के Array को Use करना चाहिए या फिर Object के References के Array को Use करना चाहिए ना कि Objects के Array को।

अब हमें Virtual Functions के का;र् करने के तरीके की Basic जानकारी है, इसलिए अब हम कुछ ऐसी स्थितियों पर विचार करते हैं, जहां Virtual Functions को Real Case में Use किया जा सकता है।

हम यहां जो अगला उदाहरण देख रहे हैं वह उदाहरण किसी School या University के लोगों को Modal करता है। किसी School या University में मुख्‍य रूप से Students व Teachers होते हैं। हम देखते हैं कि School के Students व Teachers की Category में कुछ Features समान होते हैं।

हम इस उदाहरण में Student व Teacher Class को Person Class से Derive कर रहे हैं। किसी School या University में कई अन्‍य लोग भी हो सकते हैं जो कि ना तो Teachers होते हैं ना ही Students, जैसे कि School के Trusty, Administrators, Consultants आदि। हम ये मान रहे हैं कि हमें इन Extra लोगों के लिए अलग से Class बनाने की जरूरत नहीं है, इसलिए इन सभी को हम Person Class के Objects के रूप में Create कर लेंगे।

Program को Simple बनाने के लिए हम Person Class में केवल एक ही Data Item को Define कर रहे हैं जो कि Person के नाम को Represent करता है। हालांकि इसमें हम किसी Person के विभिन्न Features जैसे कि Address, Telephone Number आदि को भी Include कर सकते हैं।

Student Class में हम Student के Grade Point Average (GPA) को Data Member के रूप में ले रहे हैं और Teacher Class में हम Data Member के रूप में Teacher द्वारा Publish किए गए Scholarly Papers की संख्‍या को ले रहे हों जो कि Publish हुई हैं। इन सभी Classes में दो Member Functions getData()putData() हैं जो Basic Input व Output का काम करते हैं। इनमें एक और Member Function isOutstanding() भी है, जो कि कुल Outstanding Teachers व Students की List को Create करता है, जो कि सभी Respected Teachers व Students को Award Day पर सम्मानित किए जाने हैं। उदाहरण Program निम्नानुसार है:

// Program
// virtual functions with person class
	#include <iostream.h>
	#include <conio.h>

	class person                    	// person class
	{
		protected:
			char name[40];

		public:
			virtual void getData()
			{ cout << "   Enter name: ";  cin >> name; }

			virtual void putData()
			{ cout << "\nName = ” << name; }

			virtual void isOutstanding()
			{  }                  	// note: empty function body
			};                          	// student class

	class student : public person
	{
		private:
			float gpa;               	// grade point average

		public:
			void getData()           	// get student data from user
			{
				person::getData();
				cout << "   Enter student's GPA: "; 
				cin >> gpa;
			}

			void putData()
			{
				person::putData();
				cout << "   GPA = ” << gpa;
			}
	
			void isOutstanding()
			{
				if (gpa > 3.5)
					cout << " (This person is outstanding)";
			}
	};                          // teacher class

	class teacher : public person
	{
		private:
			int numPubs;             	// number of papers published

		public:
		void getData()           	// get teacher data from user
		{
			person::getData();
			cout << "   Enter number of teacher's publications: "; 
			cin >> numPubs;
		}

		void putData()
		{
			person::putData();
			cout << "   Publications = ” << numPubs;
		}

		void isOutstanding()
		{
		if(numPubs > 100)
			cout << "(This person is outstanding)";
		}
	};

	void main(void)
	{
		person* persPtr[100];        	// list of pointers to persons
		int n = 0;                   	// number of persons on list
		char choice;                 	// 'p', 's', etc.

		do
		{
			cout << "Enter person, student or teacher (p/s/t): "; 
			cin >> choice;

			if(choice=='s')                   	// put new student
				persPtr[n] = new student;      	// in array

			else if(choice=='t')              	// put new teacher
				persPtr[n] = new teacher;      	// in array

			else                              	// put new person
				persPtr[n] = new person;       	// in array

			persPtr[n++]->getData();          	// get data for person

			cout << "   Enter another (y/n)? ";   // do another person?
			cin >> choice;
		} while( choice=='y' );           	// cycle until not 'y'

		for(int j=0; j<n; j++)
		{                                 	// print names of all
			persPtr[j]->putData();            	// persons, and
			persPtr[j]->isOutstanding();      	// say if outstanding
		}
		getch();
	}     // end main()

//Output
Enter person, student or teacher (p/s/t): p
   Enter name: Nandlal
   Enter another (y/n)? y
Enter person, student or teacher (p/s/t): t
   Enter name: GopalKishan
   Enter number of teacher's publications: 110
   Enter another (y/n)? y
Enter person, student or teacher (p/s/t): t
   Enter name: BalKishan
   Enter number of teacher's publications: 10
   Enter another (y/n)? y
Enter person, student or teacher (p/s/t): t
   Enter name: NandlalKishan
   Enter number of teacher's publications: 60
   Enter another (y/n)? y
Enter person, student or teacher (p/s/t): s
   Enter name: Madhav
   Enter student's GPA: 10
   Enter another (y/n)? y
Enter person, student or teacher (p/s/t): s
   Enter name: Raghav
   Enter student's GPA: 3
   Enter another (y/n)? y
Enter person, student or teacher (p/s/t): s
   Enter name: ManMohan
   Enter student's GPA: 5
   Enter another (y/n)? n

Name = Nandlal
Name = GopalKishan   Publications = 110(This person is outstanding)
Name = BalKishan   Publications = 10
Name = NandlalKishan   Publications = 60
Name = Madhav   GPA = 10 (This person is outstanding)
Name = Raghav   GPA = 3 
Name = ManMohan   GPA = 5 (This person is outstanding)

Person Class में String प्रकार का एक Single Data Item है, जो किसी Person के नाम को Represent करता है। student व teacher Classes person Base Class में एक नया Data Item Add करता है। student Class में float प्रकार का एक Data Item gpa है, जो कि Student के gpa को Represent करता है।

teacher Class में एक integer प्रकार का Variable numPubs र्है। जो Teacher द्वारा Published कुल Papers की संख्‍या को Represent करता है। यदि Student का GPA 3.5 से ज्यादा होता है और Teacher 100 से अधिक Paper Publish करवा लेता है तो Student व Teacher Outstanding हो जाते हैं।

Person Class में तीनों Functions को Virtual Declare किया गया है। ऐसा करना जरूरी है क्योंकि इन्हीं नामों के Functions Derived Class में भी Exists हैं और Derived Classes के Objects को Pointers द्वारा Access किया जा रहा है। Program को ये जानने का केवल एक ही तरीका है कि किस प्रकार के Object को निम्न Expression में persPtr[j] Pointer Point कर रहा है:

persPtr[j]->putData();

यदि putData को Virtual ना बनाया जाता तो इस Expression के कारण Base Class का ही putData Member Function Execute होता। हम देख सकते हैं कि person Class में isOutstanding Function की Body को Empty रखा गया है।

ऐसा इसलिए किया गया है क्योंकि इस Class का कोई भी Object Outstanding स्थिति को Represent नहीं करता है। हालांकि ये Function कुछ भी नहीं करता है लेकिन फिर भी हम इस Function को हटा नहीं सकते हैं। क्योंकि इस Statement की जरूरत निम्न Statement को होती है:

persPtr[j]->isOutstanding();

main() Function में हालांकि persPtr person* Type के Pointers को Hold कर सकता है लेकिन साथ ही ये student* व teacher* प्रकार के Pointers को भी Hold कर सकता है।

यदि ये निश्चित हो कि person Class का कोई भी Instance Create नहीं किया जाएगा, तो हम इस Function की Body में एक Error Message Statement लिख सकते हैं।

ध्‍यान दें कि Base Class के Virtual Member Functions को Derived Class में हम Scope Resolution Operator के प्रयोग द्वारा Call कर सकते हैं, ठीक उसी प्रकार से जिस प्रकार से Overloaded Functions को Call किया जाता है। उदाहरण के लिए student Class का getData() Member Function person Class में निम्नानुसार getData() Member Function Call कर सकता है:

	class student : public person
	{
	   ...
	   void getData()
	   {
		  person::getData();     // call base class virtual function
		  cout << “   Enter student's GPA: "; 
		  cin >> gpa;
	   }
	   ...
	   ...
	};

Virtual Functions जब Polymorphism Concept को Implement नहीं कर रहे होते हैं, तब वे बिल्कुल एक Non-Virtual Function की तरह Behave करते हैं।

हमने Graphics Program का एक उदाहरण पिछले अध्‍याय में देखा है। इस Example में Shape Class एक Specific Shape (cap, bowl और Square) को Represent करता है जो कि एक General Shape Class से Derived किए जाते हैं।

इन Complex Pictures को Display करने का एक आसान तरीका ये है कि हम इन Shape Objects के Pointers Create करें और उन्हें एक Array में Store कर दें फिर एक for Loop द्वारा विभिन्न Shapes को Draw कर लें। निम्न Program में हम यही काम कर रहे हैं। इस Program में हम draw() Function को Shape Class में Virtual Declare कर रहे हैं। शेष Program पिछले उदाहरण की तरह ही है। उदाहरण निम्नानुसार है:

	// draws shapes made from Xs on character-based display
	// uses virtual draw() function
	#include <iostream.h>
	#include <conio.h>

	class shape
	{
		private:
			int xCo, yCo;                	// coordinates of shape
			int size;                    	// size of shape

		protected:                      	// read-only functions
			int getx() const { return xCo; }
			int gety() const { return yCo; }
			int getz() const { return size; }
			void down() const;           	// declaration

		public:                         		// 3-arg constructor
			shape(int x, int y, int s) : xCo(x), yCo(y), size(s)
			{  }

			virtual void draw() const
			{
				cout << "Error: Base Class is Virtual” << endl; 
				cout << "You can not create an Instance of this class";
			}
	};

	void shape::down() const           	// move cursor down to top of shape
	{
		for(int y=0; y<yCo; y++)
			cout << endl;
	}

	class square : public shape        	// square shape
	{
		public:                         		// 3-arg constructor
			square(int x, int y, int s) : shape(x, y, s)
			{  }

			void draw() const;           	// declaration
	};

	void square::draw() const          	// draw a square
	{
		shape::down();                  	// position y at top of shape
		for(int y=0; y<getz(); y++)     	// move y down across shape
		{
			int x;
			for(x=1; x<getx(); x++)      	// space over to shape
				cout << ' ';
			for(x=0; x<getz(); x++)      	// draw line of Xs
				cout << 'X';
			cout << endl;
		}
	}

	class cap : public shape           	// cap (pyramid) shape
	{
		public:                         		// 3-arg constructor
			cap(int x, int y, int s) : shape(x, y, s)
			{  }

			void draw() const;           	// declaration
	};

	void cap::draw() const             	// draw a cap
	{
		shape::down();
		for(int y=0; y<getz(); y++)
		{
			int x;
			for(x=0; x < getx()-y+1; x++)
				cout << ' ';
			for(x=0; x<2*y+1; x++)
				cout << 'X';
			cout << endl;
		}
	}

	class bowl : public shape      	// bowl (inverted pyramid) shape
	{
		public:                     		// 3-arg constructor
			bowl(int x, int y, int s) : shape(x, y, s)
			{  }

			void draw() const;       	// declaration
	};

	void bowl::draw() const        	// draw a bowl
	{
		shape::down();
		for(int y=0; y<getz(); y++)
		{
			int x;
			for(x=0; x < getx()-(getz()-y)+2; x++)
			cout << ' ';
			for(x=0; x < 2*(getz()-y)-1; x++)
			cout << 'X';
			cout << endl;
		}
	}

	void main()
	{
		const int N = 3;                  	// number of shapes
		shape* shapeArray[N];                	// array of pointers to shapes
		bowl bw(10, 0, 3);                	// make a bowl
		square sq(20, 1, 5);              	// make a square
		cap cp(30, 1, 7);                 	// make a cap

		shapeArray[0] = &bw;                 	// put tHire addresses in array
		shapeArray[1] = &sq;
		shapeArray[2] = &cp;

		cout << endl << endl;             	// start two lines down
		for(int j=0; j<N; j++)
		// display all three shapes
			shapeArray[j]->draw();
		getch();
	}

इस Program में एक Shapes प्रकार के Pointers का Array Setup किया गया है। फिर bowl, cap व square प्रकार के तीन Objects Create किए गए हैं और उनके Addresses Array में Store किए गए हैं। फिर एक Loop द्वारा तीनों Objects को Draw किया गया है।

इस Program में हम shape प्रकार का कोई भी Object Create नहीं कर सकते हैं। shape Class को हम केवल एक Base Class की तरह ही Use कर सकते हैं, जिससे अन्‍य Classes Derive की जा सकती हैं। यानी shape Class एक Generalized या Abstract Class है।

यदि कोई shape Class के Object Create करके Draw करने की कोशिश करता है, तो shape Class के draw() Function का Execution होता है और एक Error Message Display होता है, क्योंकि हमने shape :: draw() Function में ये Error Message लिख दिया है।

ये Errors Find करने का एक बहुत ही उपयोगी व Intelligent तरीका है। हमें हमेंशा Class Create करते समय इस प्रकार के Errors को लिख देना चाहिए] ताकि Compiler Class User को इस प्रकार के Error Message Compile Time में ही प्रदान कर सके। उसे Program के Run Time का Wait ना करना पडे। यहां हम Compiler को ये बताना चाहते हैं कि यदि कोई Class User Base Class (shape) के Instance Create करने की कोशिश करे तो Compiler उसे बता दे कि वह इस Class के Objects Create नहीं कर सकता है।

विभिन्न Objects Create करके उनका Address Array में Store करने के स्थान पर हमने सीधे ही निम्न Statement द्वारा Array में विभिन्न Objects Create करके उनके Address Initialize कर दिये हैं:

	shape* shapeArray[N] = { 
		&bowl(10, 0, 3),   // initialize array
		&square(20, 1, 5),
		 &cap(30, 1, 7) 
	};

इस Class के Constructors Virtual नहीं हैं। ये Virtual हो भी नहीं सकते हैं क्योंकि एक Object का Constructor उसके Virtual Mechanism को सबसे पहले Setup करता है। हमें इसके लिए Code भी नहीं लिखने होते हैं। ठीक उसी तरह से जैसे हम vptr के लिए Code नहीं लिखते हैं। Virtual Functions तब तक Memory में Exist नहीं होते हैं जब तक कि Constructors का काम समाप्त नहीं हो जाता इसलिए Constructors कभी Virtual नहीं हो सकते।

इसी तरह से जब हम कोई Object Create कर रहे होते हैं तब हमें पता होता है कि हम किस Class का Object Create कर रहे हैं और हम Compiler को ये बात Specify भी कर सकते हैं। परिणामस्वरूप Virtual Constructor की इतनी जरूरत नहीं होती है जितनी Virtual Functions की होती है जो कि पहले से Created Objects के Pointers को Access करता है। जबकि Destructor को Virtual रखना जरूरी होता है। हम Destructor के बारे में आगे बात करेंगे।

Polymorphism का प्रयोग किसी Program के किसी हिस्से को उसी Program के अन्‍य हिस्सों से अलग (Isolate) करने के लिए भी उपयोगी होता है। जैसाकि हमने पहले कहा कि OOP Programs दो भागों में विभाजित रहते हैं, जो कि अक्सर विभिन्न Programmers द्वारा अलग-अलग समय में लिखे जाते हैं।

पहला हिस्सा Class होता है, जिसे Programmers का एक समूह लिखता है जिन्हें Class Creators कहते हैं और दूसरा हिस्सा उन Programmers का होता है जो उन Classes को Use करते हैं। Reusability का एक फायदा ये भी है कि एक ही Class को विभिन्न Programmers विभिन्न कामों के लिए बार-बार Use कर सकते हैं।

इस पुस्तक के ज्यादातर उदाहरणों में Class User के Code एक Single main() Function में लिखे गए हैं, जिससे Example समझने में आसान हो जाता है लेकिन ये पूरी तरह से Realistic नहीं है। जब Programmers जटिल Programs लिखते हैं, तब Programs को कई Functions में विभाजित किया जाता है और इन Functions को main() Function या इन्हीं Functions द्वारा आपस में Invoke किया जाता है।

इस प्रकार के जटिल Program की Programming उस स्थिति में सरल हो सकती है जब User के Code विभिन्न Classes की परवाह किए बिना किसी एक Generic Class के साथ काम करते हैं। ऐसा इसलिए हो सकता है। क्योंकि Objects इस स्थिति में सामान्‍यतया References या Pointers की तरह एक Functions से दूसरे Function में Pass व Return किए जाते हैं और यदि ये सभी Arguments और Return Values किसी एक Single Class की होती हैं, तो Coding सरल हो जाती है। दूसरे तरीके से इसी बात को कहें तो हम कह सकते हैं कि User के Code व को किसी Specific Class से Decouple करने पर Programming करना काफी सरल हो सकता है।

हमारा पहला उदाहरण यही Show करता है कि Polymorphism को तब किस प्रकार से Use किया जा सकता है, जब Function Arguments के रूप मे References का प्रयोग किया जाता है। हमारा दूसरा Example ये Show करता है कि Polymorphism का प्रयोग तब किस प्रकार से किया जा सकता है जब Function Argument के रूप में Pointers को Pass किया जाता है। (Arrays of Pointers to Objects – Geeks4Geeks )

Early Binding and Late Binding in C++ - Virtual Functions
C++ Polymorphism using Reference

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

MidRangeHub Finance Auto Loans Bank Business Health Insurance Insurance Investment Law Lif Insurance Loan Stocks how to endorse a check chase sapphire travel insurance chase sapphire travel delay when are property taxes due Tower Loans how to sell stocks on cash app Voided Check Examples Personal Finance Books Collateral Loans how to sell stocks on cashapp how do you sell your stocks on cash app how to sell stock on cash app joint account sofi joint account ally joint account capital one joint account best bank for joint account chase joint account cyber insurance coverage silverfort free cyber insurance coverage silverfort monjouro savings card Money6x Real Estate