C++ const Parameter: जब हम Function में Arguments Pass By Value देते हैं, तब ये बात अच्छी रहती है कि वास्तविक Data में किसी प्रकार का बदलाव नहीं होता है। Function जो भी काम करता है, वह सारा काम Data की एक प्रतिलिपी पर होता है।
लेकिन हमेंशा इस प्रकार से करने पर कई बार Data बहुत बडे होते हैं, जिससे इनकी बार-बार प्रतिलिपी बनने से प्रोग्राम काफी बडा हो जाता है और Program में काफी Extra Memory Use होती है। साथ ही Copying की इस प्रोसेस में समय भी काफी लगता है। इन कारणों से हम Function Argument के रूप में Object या Variable का Reference भेजते हैं। Pass by Reference से कई बार Object या Variable का वास्तविक Data भी Alter हो सकता है।
इसलिए हमें ये जरूरत होती है कि Object या Variable को Function में Reference के रूप में भेजा जाए लेकिन किसी भी तरीके से Object या Variable का Original मान भी ना बदले। इन दोनों शर्तों को पूरा करने के लिए हम Function Argument के रूप में जब Variable या Object के Reference को भेजते हैं, तो साथ में const Keyword का प्रयोग करते हैं। const का प्रयोग करने से Object या Variable के वास्तविक मान में भी कोई परिवर्तन नहीं होता है और Program की Speed पर भी फर्क नहीं पडता है। इसे समझने के लिए निम्न प्रोग्राम देखें:
// Program class omega { private: int omdata; public: void getdata(const int& i) // guarantees not to change i { omdata = i; // this is fine //i = 44; // error: can't modify const variable } }; void main() { omega om1; int ivar = 77; // I don't want getdata() to modify ivar om1.getdata(ivar); // perfectly safe }
इस Program में जब getdata() Member Function Run होता है तब Argument के रूप में ivar Variable का Reference Function को Pass होता है। लेकिन हमने Reference को const कर दिया है, इसलिए ivar के मान में कोई परिवर्तन नहीं हो सकता है। किसी Object या Variable के Original Data को सुरिक्षत रखने का ये सबसे सही तरीका है और हमें यही तरीका अपनाना चाहिए।
यदि हमें मूल Data को ही Change करना हो तभी const का प्रयोग नहीं करना चाहिए जैसे कि Swapping के Program में हमें मूल Data को ही Change करना होता है। जब हम Function में Pass By Value द्वारा किसी Variable या Object को Pass करते हैं, तब हमें const का प्रयोग नहीं करना चाहिए क्योंकि तब Function को मूल Data की एक Copy ही Pass होती है इसलिए मूल Data सुरिक्षत रहता है। अब हम Copy Constructor का एक साधारण सा प्रोग्राम देखते हैं।
// Program #include <iostream.h> class omega { private: int intvar; public: omega(int v) : intvar(v) // One-arg Constructor { } omega(const omega& om) // Copy Constructor { intvar = om.intvar; cout << "\nI am the Copy Constructor"; } }; void main() { omega om1(27); // uses One-arg Constructor omega om2=om1; // uses Copy Constructor omega om3(om1); // uses Copy Constructor }
इस Program में omega class में दो Constructor हैं। पहला One-Argument Constructor व दूसरा Copy Constructor: Copy Constructor कई मा;नों में एक अन्य One-Argument Constructor ही है। इसका नाम भी वही है जो class का है और ये भी कोई मान return नहीं करता है। फिर भी इसके Argument उसी class के होते है जिसका Member Function होता है। ये Argument Object में Copy होने वाले Argument होते हैं। ये Program दो बार om2 व om3 को Create करते समय Copy Constructor को Use करता है। यानी:
omega om2=om1; // uses Copy Constructor
omega om3(om1); // uses Copy Constructor
ये दोनो Statements Copy Constructor द्वारा om1 के मान को Create किए जाने वाले दोनों Object में Initialize करता है। Copy Constructor जितनी बार भी Call होता है, वो एक Message Print करता है और ये Massage Program के Output के रूप में निम्नानुसार Print होता है:
I am the Copy Constructor <–when om2 is Created
I am the Copy Constructor <–when om3 is Created
Copy Constructor के अन्दर लिखा गया Statement intvar = om.intvar; (Copy the data item) एक Object का Data दूसरे Object को देने के लिए जरूरी है। यदि हम ये Statement नहीं लिखते हैं तो Compiler स्वयं default Copy Constructor को Use करके Member Wise Source Object के सभी Data को Target Object में Copy कर देता है।
लेकिन यदि हम स्वयं का Copy Constructor बना रहे हैं, तो Copy होने वाले सभी Data Member किस प्रकार से Copy होंगे, इसकी सारी जिम्मेदारी हमारी होती है। यदि हम Create किए गए दोनों Objects om2 व om3 को देखते हैं, तो दोनों का ही मान 27 Print होता है। एक बात और ध्यान रखें कि Constructor में हमेंशा Same Class के Object का Reference ही भेजना चाहिए और Argument const ही होने चाहिए। Data की सुरक्षा के लिए ऐसा करना ठीक रहता है।
चलिए, अब हम समझने की कोशिश करते हैं कि स्वयं के Copy Constructor की क्या जरूरत है। हमने इसी Book में एक Car Class का प्रोग्राम बनाया था जो Create होने वाले Objects की संख्या ध्यान रखता है और हर Object को एक Serial Number प्रदान करता है। मान लो हम निम्न Statement द्वारा एक Object Create करते हैं:
Car car2(car1); // clone car2 from car1
यहां यदि हम स्वयं का Copy Constructor Use नहीं करते हैं, तो car2 को प्राप्त होने वाले सभी मान car1 के समान ही होंगे। क्योंकि Copy होने वाले सभी Data ज्यों के त्यों दूसरे Object में Copy हो जाएंगे और count का मान भी कभी Increment नहीं होगा। ऐसा इसलिए क्योंकि हमने Normal Constructor को Call नहीं किया है और Default Copy Constructor, Increment Variable, count के बारे में कुछ नहीं जानता है। इस आवश्यकता को पूरा करने के लिए हमें स्वयं का Copy Constructor बनाना होगा। इस प्रक्रिया को समझने के लिए निम्न प्रोग्राम को देखिए:
// Program #include <iostream.h> #include <string.h> // for strncpy() class omega { private: static const int size = 20; char name[size]; static int total; int number; public: // One-arg Constructor omega(char str[]) : number(++total) { strncpy(name, str, size); cout << "\nI am the 1-arg Constructor. I have Created Object " << name << "-" << number; } // Copy Constructor omega(const omega& om) { strncpy(name, om.name, size); number = ++total; cout << "\nI am the Copy Constructor. I have Created Object " << name << "-" << number; } }; int omega::total = 0; void main() { omega om1("Harriet"); // uses One-arg Constructor omega om2=om1; // uses Copy Constructor omega om3(om1); // uses Copy Constructor }
इस प्रोग्राम में class का एक Data Member है जो हर नए Create होने वाले Object को एक Serial Number प्रदान करता है साथ ही ये भी ध्यान रखता है कि कुल कितने Object Create हुए हैं। इस class में एक String Data Member भी है जिससे हर Object को एक नाम दिया जा रहा है और हर Object का नाम User स्वयं देता है। इस Program में हम चाहे जिस तरह से Object बनाते हैं, हर Object को एक Serial Number प्राप्त हो जाता है। जब Copy Constructor से एक Object Create किया जाता है, तब उस Object का नाम तो समान होता है लेकिन Object का Serial Number बदल जाता है।
main() Program में om1 नाम का omega class का एक Object Create किया गया है, जिसका नाम हमने Harriet दिया है। क्योंकि ये Program का First Object है जिसे Constructor द्वारा Automatically 1 Number दिया गया है। दूसरे व तीसरे Objects om2 व om3 को Copy Constructor om1 द्वारा Create किया गया है। इन दोनों का नाम समान ही है, क्योंकि ये Copy Constructor द्वारा बना, गए हैं। फिर भी इन्हे अलग Variable Number दिए गए हैं, क्योकि Copy Constructor वैसे ही काम करता है जैसे One-Argument Constructor करता है: ये total Counter को Increment करता है और प्राप्त मान को नए Number Value के लिए Use करता है। इस Program का Output निम्नानुसार आता है:
I am the 1-arg Constructor. I have Created Object Harriet-1
I am the Copy Constructor. I have Created Object Harriet-2
I am the Copy Constructor. I have Created Object Harriet-3
ये Program दिखाता है कि यदि हम स्वयं का Copy Constructor Use करते हैं, तो हम Object के Initialization के साथ ही काफी कुछ अन्य काम भी कर सकते हैं। हम नए Data बना सकते हैं या Data को Modify कर सकते हैं। इस Program मे Use किए गए निम्न Syntax है।
omega(char str[]) : number(++total) // <--initialization { … }
को हम दूसरे तरीके से भी लिख सकते हैं। जो निम्नानुसार है:
omega(char str[]) { number = ++total; // <--assignment … }
इन दोनों तरीको में अन्तर ये है कि पहला तरीका number को एक value Initialize करता है जबकि दूसरा तरीका number को एक Value assign करता है।
Copy Constructor का प्रयोग ये तय करने के लिए किया जाता है कि एक Object में Stored Data किस प्रकार से परिवर्तित हो कर दूसरे Object में Store हो सकते हैं। इससे data की Correctness को Check किया जा सकता है। किसी Object को कभी भी किसी Function में By Value नहीं भेजना चाहिए। क्योंकि जब हम किसी Object को किसी Function में By Value भेजते हैं, तो Function में उस Object की एक Copy Create होती है और Copy Constructor Invoke हो जाता है।
अब यदि हम उपरोक्त उदाहरण ही लें तो हमने इसमें एक Constructor द्वारा Create होने वाले सभी Object को एक Number प्रदान किया है और इस बात की जानकारी रखी है कि उस Class से कुल कितने Object Create हुए हैं। यदि इस प्रकार से हम किसी Function में Object को By Value Pass करते हैं, तब भी नया Object Create होता है और Counter का मान Increment हो जाता है क्योंकि Object के Create होते ही Constructor Execute होता है।
इस वजह से हमें सही Result प्राप्त नहीं हो सकता कि वास्तव में main() Program में उस Class के कितने Objects Create हुए हैं और उनका Number क्या है। इसलिए Object को कभी भी किसी Function में By Value नहीं भेजना चाहिए, नहीं तो कई बार ऐसे Bugs Generate होते हैं, जिन्हें खोजना नामुमकिन होता है।
इसी तरह से तब भी Object का Constructor Execute होता है, जब Program Control Function से By Value Return किया जाता है। यानी किसी Object को By Value Return करने के लिए हम अक्सर एक Temp नाम का Object Create करते हैं और ये Object Create होते ही वापस Copy Constructor को Call कर लेता है। इसलिए किसी Function से किसी Object को ना तो By Value Return करवाना चाहिए ना हि Object को By Value किसी Function में भेजना चाहिए। (C++ const Parameter – Wiki)
ये Article इस वेबसाईट पर Selling हेतु उपलब्ध EBook C++ Programming Language in Hindi से लिया गया है। इसलिए यदि ये Article आपके लिए उपयोगी रहा, तो निश्चित रूप से ये पुस्तक भी आपके लिए काफी उपयोगी साबित होगी।
C++ Programming Language in Hindi | Page: 666 | Format: PDF