Theory
दो decisions, दो clocks
कल आपने till को दो तरीक़ों से व्यवहार करते देखा: bill(50) बनाम bill(50, 0.1) compiler से चुना गया, और p.discount() सिर्फ़ तभी चुना गया जब एक असली card tap हुआ।
वही pillar, पर decision का moment पूरी तरह अलग है: एक choice program कभी शुरू होने से पहले seal हो जाती है, दूसरी call के exact instant तक खुली रहती है।
Examiners इस contrast को बहुत पसंद करते हैं: "Compile-time और run-time polymorphism differentiate कीजिए" लगभग एक guaranteed सवाल है। चलिए इस फ़र्क़ को भूलना नामुमकिन बनाते हैं।
Theory
Printed menu बनाम daily special
Canteen का printed menu printing press पर fixed हो चुका था: आप इससे जो भी order करें, kitchen का response बहुत पहले तय हो चुका था। यह compile-time है: serving शुरू होने से पहले तय।
Daily special board हर सुबह उस दिन kitchen चला रहे व्यक्ति द्वारा तय होता है। वही board, actual दिन के अनुसार अलग dish। यह run-time है: जवाब सिर्फ़ उस moment में exist करता है।
Theory
Binding: दोनों के पीछे का word
Binding का मतलब है एक function call को उस function body से जोड़ना जो run होगी।
- Early (static) binding: connection compilation के दौरान fixed होता है। Compiler
bill(50, 0.1)पढ़ता है, argument list को एक overload से match करता है, और call को hard-wire करता है। - Late (dynamic) binding: connection program चलते हुए बनता है। Call
p.discount()जिस भी object को p असल में refer करता है उस तक route होती है, उसी moment check होते हुए।
Compile-time polymorphism early binding इस्तेमाल करता है; run-time polymorphism late binding इस्तेमाल करता है।
At a glance
Exam table
| Aspect | Compile-time | Run-time |
|---|---|---|
| Also called | Static, early binding | Dynamic, late binding |
| तय होता है | Compilation के दौरान | Execution के दौरान |
| इससे achieve होता है | Function + operator overloading | Virtual functions + inheritance |
| Inheritance चाहिए? | नहीं | हाँ, base pointer/reference के साथ |
| Speed | तेज़ (call hard-wired) | थोड़ा धीमा (looked up) |
| Flexibility | Build पर fixed | असली object के अनुसार adapt होता है |
Practical
एक program में दोनों clocks
#include <iostream>
using namespace std;
class Person {
public:
virtual double discount() { return 0.0; } // virtual: late binding
};
class Student : public Person {
public:
double discount() { return 0.10; } // overrides Person's
};
// COMPILE-TIME: two overloads, picked by argument list
double bill(double amt) { return amt; }
double bill(double amt, double disc) { return amt * (1 - disc); }
int main() {
cout << bill(50.0) << endl; // compiler chose overload 1
cout << bill(50.0, 0.2) << endl; // compiler chose overload 2
Person *p = new Student(); // base pointer, derived object
cout << p->discount() << endl; // 0.10: decided AT RUN TIME
delete p;
return 0;
}
Think first
एक word हटाइए, answer बदलिए
ऊपर के code में, Person::discount() से word virtual delete कीजिए। अब p->discount() क्या print करता है, और क्यों?
Show the answer
यह 0 print करता है, Person version। virtual के बिना, compiler call को early, pointer के type से bind करता है: p एक Person pointer है, तो Person::discount() hard-wired है, चाहे वहाँ असल में कोई भी object रहे। एक keyword early और late binding के बीच पूरा फ़र्क़ है, यही कारण है exams virtual के साथ और बिना output पूछना पसंद करते हैं।
Quiz
Run-time polymorphism के बारे में कौन सा statement TRUE है?
- इसे inheritance चाहिए और यह virtual functions से achieve होता है
- यह compile-time polymorphism से तेज़ है क्योंकि decisions ज़्यादा fresh हैं
- Function overloading इसका सबसे common example है
- Compiler इसे argument types check करके resolve करता है
Show the answer
इसे inheritance चाहिए और यह virtual functions से achieve होता है
Run-time polymorphism सिर्फ़ एक inheritance hierarchy के पार exist करता है, base pointers/references के through virtual functions से dispatched। यह थोड़ा धीमा है (program call time पर target ढूँढता है), तेज़ नहीं, तो B ग़लत है। C और D compile-time polymorphism describe करते हैं: overloading, compilation के दौरान argument list से resolved। दोनों families को swap करना यहाँ classic lost mark है।
Watch out
जहाँ answers marks खोते हैं
Examiners तीन precision points check करते हैं:
- Compile-time के लिए "early/static binding" कहिए और run-time के लिए "late/dynamic binding"; synonyms ही marks हैं।
virtualके बिना overriding run-time polymorphism NAHI है: base pointer अभी भी base version call करता है।- Templates भी compile-time polymorphism count होते हैं; इन्हें सिर्फ़ तभी mention कीजिए अगर आपका paper इन्हें cover करता है, वरना overloading पर टिके रहिए।
Theory
वह rule of thumb जो हमेशा काम करता है
एक सवाल पूछिए: क्या compiler पहले से जान सकता था? अगर argument list तय करती है (overloading), तो हाँ, compile-time। अगर answer इस पर depend करता है कि run होते हुए एक pointer किस object को होल्ड करता है, तो नहीं, run-time। अगले lessons हर family में गहराई से जाते हैं: पहले overloading बनाम overriding, फिर virtual functions ख़ुद।
Summary
Key takeaways
- Binding = एक call को एक function body से link करना; compilation पर early binding, execution पर late binding।
- Compile-time polymorphism: function/operator overloading, argument list से resolved, तेज़।
- Run-time polymorphism: base pointers/references के through virtual functions + inheritance, flexible।
- virtual keyword के बिना, pointer का type तय करता है: base version run होता है (early binding)।
- Run-time को inheritance चाहिए; compile-time को नहीं।
- Memory hook: printed menu बनाम daily special board।