ఫంక్షన్స్ & Function Overloading
ఒక పెద్ద సాఫ్ట్వేర్ అప్లికేషన్లో వేలాది లైన్ల కోడ్ ఉంటుంది. ఆ కోడ్ మొత్తాన్ని ఒకే main() ఫంక్షన్లో రాసుకుంటూ పోతే, అది చదవడానికి అసాధ్యమైన గందరగోళ మోనోలిత్గా మారిపోతుంది. సాఫ్ట్వేర్ ఇంజనీరింగ్లో అత్యంత కీలకమైన ఆర్కిటెక్చర్ సూత్రం మాడ్యులరైజేషన్ (Modular Programming) — అంటే ఒక పెద్ద సమస్యను స్వతంత్రమైన చిన్న చిన్న భాగాలుగా విభజించడం.
ఆ స్వతంత్ర విభాగాలనే మనం ఫంక్షన్స్ (Functions) అంటాం. ఈ సమగ్ర మాస్టర్క్లాస్లో మనం:
1 ఫంక్షన్స్ అంటే ఏమిటి? మాడ్యులర్ ప్రోగ్రామింగ్ & Code Reusability
ఒక నిర్దిష్టమైన పనిని (Specific Task) పూర్తి చేయడానికి రూపొందించబడిన స్వయంప్రతిపత్తి గల కోడ్ బ్లాక్ను ఫంక్షన్ (Function) అంటారు.
సాఫ్ట్వేర్ పరిశ్రమలో ఫంక్షన్స్ ఎందుకు ప్రాణాధారమైనవి?
- Code Reusability (కోడ్ పునర్వినియోగం): ఒకే లాజిక్ను (ఉదా: జిఎస్టి పన్ను లెక్కించడం) ప్రోగ్రామ్లో పది చోట్ల రాయకుండా, ఒక ఫంక్షన్గా రాసి ఎన్నిసార్లైనా పిలుచుకోవచ్చు (Call).
- Single Responsibility Principle (SRP): ప్రతి ఫంక్షన్ ఒకే ఒక్క పనిని పరిపూర్ణంగా చేయాలి. దీనివల్ల డీబగ్గింగ్ చేయడం చాలా సులభమవుతుంది.
- Abstraction (అబ్స్ట్రాక్షన్): ఫంక్షన్ను వాడేవారికి అది లోపల ఎలా పనిచేస్తుందో తెలియాల్సిన అవసరం లేదు; ఇన్పుట్ ఏమిటి మరియు అవుట్పుట్ ఏమి వస్తుందో తెలిస్తే చాలు (ఉదా:
std::sqrt(25)).
🧩 ఒక ఫంక్షన్ యొక్క 4 ముఖ్యమైన భాగాలు
// ఫంక్షన్ బాడీ: వ్యాపార లాజిక్
return [ఫలితం];
}
2 ఫంక్షన్ డిక్లరేషన్ (Prototype) vs డెఫినిషన్ (Definition)
C++ కంపైలర్ ఒక ఫైల్ను పై నుండి క్రిందికి (Top-to-Bottom) ఒకే పాస్లో చదువుతుంది. మీరు main() ఫంక్షన్ కింద ఒక ఫంక్షన్ను రాసి, దాన్ని main() లోపల పిలిస్తే — కంపైలర్ "error: identifier not found" అని ప్రోగ్రామ్ను తిరస్కరిస్తుంది!
ఈ సమస్యను పరిష్కరించడానికి C++ లో రెండు దశలు ఉన్నాయి:
- 1. ఫంక్షన్ డిక్లరేషన్ (Function Prototype):
main()కంటే ముందే కంపైలర్కు ఫంక్షన్ పేరు, రిటర్న్ టైప్, మరియు పారామీటర్లను పరిచయం చేయడం. ఇది కేవలం ఒక హామీ పత్రం లాంటిది (సెమికోలన్;తో ముగుస్తుంది). - 2. ఫంక్షన్ డెఫినిషన్ (Function Definition): ఫంక్షన్ లోపల అసలు కోడ్ ఏమి చేయాలో కర్లీ బ్రాకెట్లలో
{ ... }పూర్తిగా రాయడం.
#include <iostream>
// 1. ఫంక్షన్ ప్రోటోటైప్ (డిక్లరేషన్): కంపైలర్కు ముందస్తు సమాచారం
double calculateGst(double basePrice, double gstPercentage);
int main() {
double itemPrice = 12000.00;
double taxRate = 18.0;
// ఫంక్షన్ కాల్: కంపైలర్కు ప్రోటోటైప్ ముందే తెలుసు కాబట్టి ఎలాంటి ఎర్రర్ రాదు
double finalTax = calculateGst(itemPrice, taxRate);
std::cout << "వస్తువు ధర : ₹ " << itemPrice << '\n';
std::cout << "GST పన్ను (" << taxRate << "%) : ₹ " << finalTax << '\n';
std::cout << "మొత్తం చెల్లించాల్సింది : ₹ " << (itemPrice + finalTax) << '\n';
return 0;
}
// 2. ఫంక్షన్ డెఫినిషన్: అసలైన ఇంప్లిమెంటేషన్ ఇక్కడ ఉంది
double calculateGst(double basePrice, double gstPercentage) {
return (basePrice * gstPercentage) / 100.0;
}
3 పారామీటర్ పాసింగ్ మెకానిజమ్స్: Pass by Value (కాపీ ఓవర్హెడ్)
C++ లో సాధారణంగా ఒక వేరియబుల్ను ఫంక్షన్కు పంపినప్పుడు (ఉదా: void update(int x)), కంపైలర్ ఆ ఒరిజినల్ వేరియబుల్ యొక్క పూర్తి నకలును (Duplicate Copy) స్టాక్ మెమరీలో తయారుచేసి ఫంక్షన్కు ఇస్తుంది. దీనినే Pass by Value అంటారు.
🔍 Pass by Value లక్షణాలు
1. సేఫ్టీ: ఫంక్షన్ లోపల మీరు ఆ పారామీటర్ను ఎంత మార్చినా, main() లోని ఒరిజినల్ వేరియబుల్ సురక్షితంగా ఉంటుంది (Side-effect Free).
2. పరిమితి: పెద్ద ఆబ్జెక్టులు (ఉదాహరణకు 10 లక్షల ఎలిమెంట్లు ఉన్న std::vector) పాస్ చేసినప్పుడు, ఆ మొత్తం మెమరీ మళ్లీ కాపీ అవ్వడం వల్ల ప్రోగ్రామ్ వేగం విపరీతంగా పడిపోతుంది (Memory & CPU Penalty).
4 పారామీటర్ పాసింగ్ మెకానిజమ్స్: Pass by Reference (&) (డైరెక్ట్ మోడిఫికేషన్)
ఒక వేరియబుల్ను కాపీ చేయకుండా, నేరుగా ఆ ఒరిజినల్ వేరియబుల్ పైనే ఫంక్షన్ పనిచేయాలి అనుకున్నప్పుడు మనం Pass by Reference ఉపయోగిస్తాం.
పారామీటర్ టైప్ పక్కన ఆంపర్సండ్ (&) గుర్తు పెడితే, అది కొత్త మెమరీని తీసుకోదు; ఒరిజినల్ వేరియబుల్కు ఒక మారుపేరుగా (Alias) వ్యవహరిస్తుంది. ఫంక్షన్ లోపల చేసే ప్రతి మార్పూ నేరుగా కాలర్ యొక్క వేరియబుల్ను ప్రభావితం చేస్తుంది!
#include <iostream>
// Pass by Reference: నేరుగా ఒరిజినల్ మెమరీ లొకేషన్లనే మారుస్తుంది!
void swapValues(int& first, int& second) {
int temp = first;
first = second;
second = temp;
}
int main() {
int bankAccountA = 25000;
int bankAccountB = 75000;
std::cout << "స్వాప్ చేయడానికి ముందు:\n";
std::cout << "ఖాతా A: ₹" << bankAccountA << " | ఖాతా B: ₹" << bankAccountB << "\n";
swapValues(bankAccountA, bankAccountB);
std::cout << "\nస్వాప్ చేసిన తర్వాత (Pass by Reference ప్రభావం):\n";
std::cout << "ఖాతా A: ₹" << bankAccountA << " | ఖాతా B: ₹" << bankAccountB << "\n";
return 0;
}
5 Modern C++ గోల్డెన్ రూల్: Pass by Const Reference (const Type&)
C++ సాఫ్ట్వేర్ ఇంజనీరింగ్లో అత్యంత శక్తివంతమైన, ప్రపంచవ్యాప్తంగా ప్రతి ప్రొఫెషనల్ కోడ్బేస్లో కనిపించే సిగ్నేచర్: const Type&!
🏆 The Best of Both Worlds (కాపీ ఉండదు + మార్చలేరు)
1. రెఫరెన్స్ (&): ఆబ్జెక్ట్ ఎంత పెద్దదైనా సరే (ఉదా: 50MB ఫైల్ డేటా లేదా భారీ స్ట్రింగ్), ఒక్క బైట్ కూడా కాపీ అవ్వదు! మెమరీ అడ్రస్ ద్వారా నేరుగా యాక్సెస్ లభిస్తుంది (Zero Copy Performance).
2. కాన్స్ట్ (const): ఫంక్షన్ లోపల డెవలపర్ పొరపాటున కూడా ఆ డేటాను మార్చలేడు (Read-Only Safety). మార్చడానికి ప్రయత్నిస్తే కంపైలర్ అక్కడే ఎర్రర్ ఇస్తుంది.
3. లిటరల్స్ మద్దతు: సాధారణ నాన్-కాన్స్ట్ రెఫరెన్స్కు డైరెక్ట్ విలువలు (ఉదా: print("హలో")) పంపలేము; కానీ const std::string& లిటరల్స్ మరియు తాత్కాలిక వస్తువులను కూడా సంతోషంగా స్వీకరిస్తుంది!
#include <iostream>
#include <string>
// గోల్డెన్ సిగ్నేచర్: const std::string& (జీరో కాపీ + రీడ్ ఓన్లీ)
void logSecurityAudit(const std::string& serverModule, const std::string& eventMessage) {
std::cout << "🔒 [SECURITY AUDIT] [" << serverModule << "]: " << eventMessage << '\n';
// serverModule = "Hack"; // ❌ Compile Error! const కాబట్టి డేటా సురక్షితం!
}
int main() {
std::string moduleName = "AUTH_SERVICE_GATEWAY";
logSecurityAudit(moduleName, "యూజర్ విజయవంతంగా 2FA ద్వారా లాగిన్ అయ్యారు.");
logSecurityAudit("PAYMENT_SERVICE", "రూ. 5000 లావాదేవీ ఆమోదించబడింది."); // టెంపరరీ లిటరల్స్ కూడా వర్తిస్తాయి
return 0;
}
6 డిఫాల్ట్ ఆర్గ్యుమెంట్స్ (Default Arguments): ఫ్లెక్సిబుల్ ఫంక్షన్ కాలింగ్
ఒక ఫంక్షన్ను పిలిచేటప్పుడు కొన్ని పారామీటర్లకు విలువలు పంపకపోతే, కంపైలర్ స్వయంచాలకంగా ముందే నిర్వచించిన డిఫాల్ట్ విలువలను (Default Values) తీసుకోవడాన్నే Default Arguments అంటారు.
⚠️ The Right-to-Left Rule (కుడి నుండి ఎడమకు మాత్రమే)
C++ లో డిఫాల్ట్ విలువలు ఎల్లప్పుడూ పారామీటర్ లిస్ట్ చివర (కుడివైపున) మాత్రమే ఉండాలి! మధ్యలో లేదా మొదట్లో ఒక పారామీటర్కు డిఫాల్ట్ విలువ ఇచ్చి, దాని కుడివైపున ఉన్న పారామీటర్కు డిఫాల్ట్ విలువ ఇవ్వకపోతే కంపైలర్ తిరస్కరిస్తుంది.
✅ void sendEmail(string to, string subject = "Info", bool urgent = false); (సరైనది)
❌ void sendEmail(string to, string subject = "Info", bool urgent); (తప్పు!)
#include <iostream>
#include <iomanip>
// డిఫాల్ట్ ఆర్గ్యుమెంట్స్: వడ్డీ రేటు 8.5%, కాలపరిమితి 12 నెలలు డిఫాల్ట్
double calculateEmi(double principal, double annualRoi = 8.5, int tenureMonths = 12) {
double monthlyRate = (annualRoi / 12.0) / 100.0;
double interest = principal * monthlyRate * tenureMonths;
return (principal + interest) / tenureMonths;
}
int main() {
std::cout << std::fixed << std::setprecision(2);
// 1. అన్నీ డిఫాల్ట్ పారామీటర్లతో పిలవడం (కేవలం ప్రిన్సిపల్ మాత్రమే ఇచ్చాం)
std::cout << "కేస్ 1 (డిఫాల్ట్ 8.5% ROI, 12 నెలలు) EMI: ₹ " << calculateEmi(100000.0) << '\n';
// 2. వడ్డీ రేటును ఓవర్రైడ్ చేయడం (10.0% ROI, 12 నెలలు)
std::cout << "కేస్ 2 (10.0% ROI, డిఫాల్ట్ 12 నెలలు) EMI: ₹ " << calculateEmi(100000.0, 10.0) << '\n';
// 3. మూడింటినీ సొంత విలువల ద్వారా పిలవడం (9.0% ROI, 36 నెలలు)
std::cout << "కేస్ 3 (9.0% ROI, 36 నెలలు) EMI: ₹ " << calculateEmi(100000.0, 9.0, 36) << '\n';
return 0;
}
7 ఫంక్షన్ ఓవర్లోడింగ్ (Function Overloading): కంపైల్-టైమ్ పాలిమార్ఫిజం
ఒకే పేరుతో ఒకటి కంటే ఎక్కువ ఫంక్షన్లను రాసే సదుపాయాన్ని ఫంక్షన్ ఓవర్లోడింగ్ (Function Overloading) అంటారు. ఇది C++ లోని Compile-Time Polymorphism కు అద్భుతమైన ఉదాహరణ.
📜 ఫంక్షన్ ఓవర్లోడింగ్ యొక్క కచ్చితమైన నిబంధనలు
కంపైలర్ ఏ ఫంక్షన్ను పిలవాలో నిర్ణయించడానికి ఫంక్షన్ యొక్క పారామీటర్ సిగ్నేచర్ ను మాత్రమే పరిశీలిస్తుంది. క్రింది మూడింటిలో కనీసం ఒకటి మారాలి:
1. పారామీటర్ల సంఖ్య (Number of Parameters): ఉదా: add(int, int) vs add(int, int, int).
2. పారామీటర్ల డేటా టైప్స్ (Data Types): ఉదా: add(int, int) vs add(double, double).
3. పారామీటర్ల క్రమం (Order of Types): ఉదా: print(int, string) vs print(string, int).
⚠️ అతి ముఖ్యమైన హెచ్చరిక: కేవలం Return Type మాత్రమే వేరుగా ఉంటే C++ లో ఫంక్షన్ ఓవర్లోడింగ్ సాధ్యం కాదు! ఉదాహరణకు: int get() మరియు double get() రాస్తే కంపైలర్ తీవ్రమైన అంబిగ్యుటీ ఎర్రర్ ఇస్తుంది.
#include <iostream>
// 1. చతురస్రం వైశాల్యం (ఒకే ఒక పూర్ణాంక పారామీటర్)
int calculateArea(int side) {
return side * side;
}
// 2. దీర్ఘచతురస్రం వైశాల్యం (రెండు పూర్ణాంక పారామీటర్లు)
int calculateArea(int length, int breadth) {
return length * breadth;
}
// 3. వృత్తం వైశాల్యం (ఒక డబుల్ పారామీటర్)
double calculateArea(double radius) {
return 3.14159 * radius * radius;
}
int main() {
std::cout << "చతురస్రం వైశాల్యం (భుజం 5) : " << calculateArea(5) << " చ.సెం.మీ\n";
std::cout << "దీర్ఘచతురస్రం వైశాల్యం (10 x 4) : " << calculateArea(10, 4) << " చ.సెం.మీ\n";
std::cout << "వృత్తం వైశాల్యం (వ్యాసార్థం 3.5) : " << calculateArea(3.5) << " చ.సెం.మీ\n";
return 0;
}
8 హార్డ్వేర్ & అసెంబ్లీ సీక్రెట్: C++ నేమ్ మ్యాంగ్లింగ్ (Name Mangling)
C భాషలో ఫంక్షన్ ఓవర్లోడింగ్ ఎందుకు లేదు? C++ లో ఇది ఎలా సాధ్యమైంది? దీని వెనుక ఉన్న అంతర్గత కంపైలర్ ఇంజనీరింగ్ అద్భుతమే నేమ్ మ్యాంగ్లింగ్ (Name Mangling లేదా Symbol Decoration).
⚙️ అసెంబ్లీలో ఫంక్షన్ పేర్లు ఎలా రూపాంతరం చెందుతాయి?
కంపైలర్ అసెంబ్లీ కోడ్ ఉత్పత్తి చేసేటప్పుడు, ఫంక్షన్ పేరుతో పాటు దాని పారామీటర్ల టైప్స్ అన్నింటినీ కలిపి ఒక ప్రత్యేకమైన యూనిక్ సింబల్ పేరును సృష్టిస్తుంది:
calculateArea(int, int) ➔ _Z13calculateAreaii
calculateArea(double) ➔ _Z13calculateAread
లింకర్ (Linker) స్థాయిలో అసెంబ్లీకి మూడు వేర్వేరు ఫంక్షన్ పేర్లు కనిపిస్తాయి కాబట్టి ఎటువంటి వివాదం తలెత్తదు! ఇక పాత C కోడ్ను C++ తో లింక్ చేయాలంటే మ్యాంగ్లింగ్ కాకుండా ఉండటానికి extern "C" { ... } అని రాస్తారు.
9 ఇన్లైన్ ఫంక్షన్స్ (Inline Functions & inline Keyword)
సాధారణంగా ఒక ఫంక్షన్ను కాల్ చేసినప్పుడు CPU లో కొన్ని పనులు జరగాలి: ప్రస్తుత రిజిస్టర్లను స్టాక్పై భద్రపరచడం, ఆర్గ్యుమెంట్లను స్టాక్కు నెట్టడం, ఫంక్షన్ ఉన్న మెమరీ లొకేషన్కు జంప్ చేయడం, కోడ్ పూర్తయిన తర్వాత తిరిగి మెయిన్కు జంప్ చేయడం. కేవలం return a + b; లాంటి చిన్న లైన్ల కోసం ఈ జంప్స్ అన్నీ చేయడం వల్ల రన్టైమ్ ఆలస్యం (Function Call Overhead) జరుగుతుంది.
ఫంక్షన్ డెఫినిషన్ ముందు inline కీవర్డ్ పెడితే, కంపైలర్ ఫంక్షన్ కాల్ బదులుగా నేరుగా ఆ కోడ్ను పిలిచిన చోటే పేస్ట్ చేస్తుంది! దీనివల్ల జంప్స్ లేకపోవడం వల్ల ఎగ్జిక్యూషన్ సూపర్ ఫాస్ట్ గా మారుతుంది.
inline int getMaximum(int a, int b) {
return (a > b) ? a : b; // కాల్ ఓవర్హెడ్ లేకుండా నేరుగా ఇన్-లైన్ గా మారిపోతుంది!
}
10 Modern C++11/C++20: Trailing Return Types & constexpr Functions
Modern C++ లో ఫంక్షన్ డిజైన్ను మరింత ఆధునీకరించడానికి సరికొత్త సింటాక్స్ ప్రవేశపెట్టబడింది:
- Trailing Return Types (
auto -> Type): రిటర్న్ టైప్ను ముందు కాకుండా బాణపు గుర్తుతో చివర పెట్టడం:auto calculate(double x) -> double. ఇది సంక్లిష్టమైన టెంప్లేట్ మెటాప్రోగ్రామింగ్లో ఆటోమేటిక్ టైప్ డిడక్షన్ కోసం చాలా ఉపయోగపడుతుంది. constexprFunctions: ఇన్పుట్ విలువలు కంపైల్-టైమ్ స్థిరరాశులు అయితే, ఆ ఫంక్షన్ను ప్రోగ్రామ్ రన్ అవ్వకముందే, కంపైలేషన్ సమయంలోనే లెక్కించి స్థిర సంఖ్యగా మార్చేస్తుంది (Zero Runtime Cost)!
11 స్టాక్ మెమరీ, కాల్ స్టాక్ (Call Stack) & ఫంక్షన్ కాల్ లైఫ్సైకిల్
ప్రతిసారి మీ ప్రోగ్రామ్లో ఒక ఫంక్షన్ కాల్ జరిగినప్పుడు, RAM మెమరీలోని స్టాక్ సెగ్మెంట్ (Stack Segment) లో ఒక కొత్త స్టాక్ ఫ్రేమ్ (Stack Frame / Activation Record) కేటాయించబడుతుంది:
│ రిటర్న్ అడ్రస్ (ఫంక్షన్ ముగిసాక ఎక్కడికి వెళ్ళాలి?) │
├──────────────────────────────────────────────┤
│ ఫంక్షన్ పారామీటర్లు (Function Arguments) │
├──────────────────────────────────────────────┤
│ లోకల్ వేరియబుల్స్ (Local Scope Variables) │
└──────────────────────────────────────────────┘
ఫంక్షన్ ముగియగానే (Return) ఆ స్టాక్ ఫ్రేమ్ తక్షణమే ఆటోమేటిక్గా నాశనమైపోతుంది (Popped from Stack). ఒకవేళ రికర్సివ్ ఫంక్షన్ ఆగకుండా తిరుగుతూ ఉంటే స్టాక్ మెమరీ నిండిపోయి Stack Overflow ఎర్రర్ వస్తుంది.
12 సాధారణ బిగినర్ తప్పులు, బగ్స్ & అంబిగ్యుటీ ట్రాప్స్
int& getNumber() {
int localVal = 100;
return localVal; // ⚠️ ఘోరమైన తప్పు! ఫంక్షన్ ముగియగానే localVal నాశనమైపోతుంది!
} // బయట ఆ రెఫరెన్స్ను వాడితే క్రాష్ లేదా గార్బేజ్ వాల్యూ వస్తుంది (Dangling Reference)!
void print(int x);
void print(int x, int y = 20);
// main లో:
print(5); // ❌ Compile Error: call of overloaded 'print(5)' is ambiguous!
// కంపైలర్కు మొదటి ఫంక్షనా లేక రెండవ దాంట్లో డిఫాల్ట్ విలువతో పిలవాలా అర్థం కాదు!
13 రియల్-వరల్డ్ ప్రాక్టీస్ ప్రాజెక్ట్: "Enterprise Corporate Payroll & Salary Taxation Engine"
ఈ అధ్యాయంలో నేర్చుకున్న ఫంక్షన్ కాన్సెప్ట్స్ — Function Overloading, Pass by Const Reference, Pass by Reference, Default Arguments, మరియు Inline Functions అన్నింటినీ సమన్వయం చేస్తూ — పూర్తి స్థాయి "Enterprise Corporate Payroll & Salary Engine" ప్రాజెక్ట్ను రన్ చేద్దాం:
#include <iostream>
#include <string>
#include <iomanip>
// ఉద్యోగి వివరాల నిర్మాణం
struct EmployeeRecord {
std::string empId;
std::string name;
std::string role;
double baseSalary;
};
// 1. ఇన్లైన్ ఫాస్ట్ హెల్పర్స్: PF మరియు మెడికల్ ఇన్సూరెన్స్ డిడక్షన్స్
inline double getProvidentFund(double baseSalary) {
return baseSalary * 0.12; // 12% PF కంట్రిబ్యూషన్
}
// 2. ఫంక్షన్ ఓవర్లోడింగ్ 1: పూర్తి-సమయ శాశ్వత ఉద్యోగుల జీతం (Full-Time Employee)
// Default Argument: వార్షిక పనితీరు బోనస్ డిఫాల్ట్ 8.0%
double calculateSalary(const EmployeeRecord& emp, double performanceBonusPercent = 8.0) {
double bonusAmount = (emp.baseSalary * performanceBonusPercent) / 100.0;
double pfDeduction = getProvidentFund(emp.baseSalary);
double professionalTax = 200.00; // స్థిర వృత్తి పన్ను
return (emp.baseSalary + bonusAmount) - (pfDeduction + professionalTax);
}
// 3. ఫంక్షన్ ఓవర్లోడింగ్ 2: గంటల వారీ కాంట్రాక్ట్ ఉద్యోగుల జీతం (Contractor by Hourly Rate)
double calculateSalary(double hourlyRate, int hoursWorked) {
double regularPay = hourlyRate * hoursWorked;
double contractorTds = regularPay * 0.10; // 10% TDS డిడక్షన్
return regularPay - contractorTds;
}
// 4. ఫంక్షన్ ఓవర్లోడింగ్ 3: ప్రాజెక్ట్ ఆధారిత ఫ్రీలాన్సర్స్ (Project Milestone Flat Payout)
double calculateSalary(double projectMilestoneFee) {
double gstDeduction = projectMilestoneFee * 0.05; // 5% విత్హోల్డింగ్
return projectMilestoneFee - gstDeduction;
}
// 5. Pass by Reference: వార్షిక ప్రమోషన్ ఇంక్రిమెంట్ అప్లై చేయడం
void applyPromotionIncrement(EmployeeRecord& emp, double hikePercent) {
emp.baseSalary += (emp.baseSalary * hikePercent) / 100.0;
emp.role = "సీనియర్ " + emp.role;
}
int main() {
std::cout << std::fixed << std::setprecision(2);
std::cout << "========================================================================================\n";
std::cout << " 🏢 TATA ENTERPRISE GLOBAL PAYROLL DISBURSEMENT & TAXATION ENGINE \n";
std::cout << "========================================================================================\n";
EmployeeRecord devEmp = {"TCS-8921", "శ్రీనివాస మూర్తి (Srinivas Murthy)", "సాఫ్ట్వేర్ ఇంజనీర్", 85000.00};
// 1. ఫుల్-టైమ్ ఉద్యోగి ప్రాసెసింగ్ (Default bonus)
double netFullTimePay = calculateSalary(devEmp);
std::cout << "1. ఫుల్-టైమ్ ఉద్యోగి: " << devEmp.name << " (" << devEmp.role << ")\n";
std::cout << " బేసిక్ జీతం : ₹ " << devEmp.baseSalary << '\n';
std::cout << " నికర చెల్లింపు (Net) : ₹ " << netFullTimePay << " (PF & బోనస్ సర్దుబాటు తర్వాత)\n";
// 2. కాంట్రాక్టర్ ప్రాసెసింగ్ (Overloaded Function 2)
double netContractorPay = calculateSalary(1250.00, 160); // ₹1250/hour, 160 hours
std::cout << "\n2. క్లౌడ్ ఆర్కిటెక్ట్ కాంట్రాక్టర్ (160 గంటలు @ ₹1250/hr):\n";
std::cout << " నికర చెల్లింపు (Net) : ₹ " << netContractorPay << " (10% TDS తీసివేత తర్వాత)\n";
// 3. ఫ్రీలాన్సర్ ప్రాసెసింగ్ (Overloaded Function 3)
double netFreelancePay = calculateSalary(150000.00); // ప్రాజెక్ట్ మైల్స్టోన్ ఫీజు
std::cout << "\n3. UI/UX డిజైన్ ఫ్రీలాన్సర్ (మొబైల్ యాప్ మైల్స్టోన్):\n";
std::cout << " నికర చెల్లింపు (Net) : ₹ " << netFreelancePay << " (విత్హోల్డింగ్ తర్వాత)\n";
// 4. Pass by Reference ప్రభావం: ప్రమోషన్ ప్రక్రియ
std::cout << "\n----------------------------------------------------------------------------------------\n";
std::cout << "🎉 [వార్షిక ప్రమోషన్ ప్రక్రియ - Pass by Reference ప్రత్యక్ష డెమో]:\n";
applyPromotionIncrement(devEmp, 15.0); // 15% శాలరీ పెంపు
std::cout << "హోదా అప్డేట్ : " << devEmp.role << '\n';
std::cout << "కొత్త బేసిక్ జీతం : ₹ " << devEmp.baseSalary << '\n';
std::cout << "సవరించిన నికర జీతం : ₹ " << calculateSalary(devEmp, 12.0) << " (12% హై-పర్ఫార్మెన్స్ బోనస్తో)\n";
std::cout << "========================================================================================\n";
return 0;
}
❓ ఇంటర్వ్యూ & పరీక్షల క్విజ్ (Knowledge Check)
ప్రశ్న 1: C++ లో కేవలం Return Type మాత్రమే వేరుగా ఉంటే ఫంక్షన్ ఓవర్లోడింగ్ ఎందుకు సాధ్యం కాదు?
func() అని పిలిచి, దాని రిటర్న్ వాల్యూను ఏ వేరియబుల్కూ అసైన్ చేయకుండా వదిలేస్తే (కేవలం func(); అని రాస్తే), కంపైలర్కు int func() ని పిలవాలో లేక double func() ని పిలవాలో నిర్ణయించడం అసాధ్యం. ఈ అంబిగ్యుటీ (Ambiguity) కారణంగా C++ కేవలం రిటర్న్ టైప్ పై ఓవర్లోడింగ్ను అనుమతించదు.
ప్రశ్న 2: Modern C++ లో 'const Type&' పారామీటర్ పాసింగ్ను ఎందుకు గోల్డెన్ ప్రామాణికంగా పరిగణిస్తారు?
&) ఉండటం వల్ల అసలు ఆబ్జెక్ట్ కాపీ అవ్వదు (Zero Copy Performance). 2. const ఉండటం వల్ల ఫంక్షన్ లోపల డేటా అనుకోకుండా మారకుండా రక్షణ లభిస్తుంది (Read-Only Safety) మరియు ఇది లిటరల్స్ లేదా టెంపరరీ ఆబ్జెక్టులను కూడా పారామీటర్లుగా స్వీకరించగలదు.
ప్రశ్న 3: నేమ్ మ్యాంగ్లింగ్ (Name Mangling) అంటే ఏమిటి? C++ లో ఇది ఎందుకు జరుగుతుంది?
ప్రశ్న 4: ఇన్లైన్ ఫంక్షన్ (inline) CPU పెర్ఫార్మెన్స్ను ఎలా మెరుగుపరుస్తుంది? ఎప్పుడు ఇన్-లైన్ చేయకూడదు?
inline ఫంక్షన్ను పిలిచినప్పుడు ఫంక్షన్ జంప్ మరియు స్టాక్ ఫ్రేమ్ క్రియేషన్ లేకుండా, నేరుగా ఆ కోడ్నే అక్కడ రీప్లేస్ చేస్తుంది, దీనివల్ల ఫంక్షన్ కాల్ ఓవర్హెడ్ తప్పుతుంది. అయితే చాలా పెద్ద ఫంక్షన్లను లేదా లూప్లు ఉన్నవాటిని ఇన్-లైన్ చేస్తే ఎగ్జిక్యూటబుల్ ఫైల్ సైజు విపరీతంగా పెరిగిపోయి (Code Bloat) CPU ఇన్స్ట్రక్షన్ క్యాష్ మిస్లకు దారితీస్తుంది.
ప్రశ్న 5: లోకల్ వేరియబుల్కు రెఫరెన్స్ (int&) రిటర్న్ చేస్తే ఏమవుతుంది? దానిని ఎలా సరిచేయాలి?
ఈ ప్రాజెక్ట్ను లైవ్గా మన కంపైలర్లో రన్ చేయండి!
ఎటువంటి లోకల్ సెటప్ లేకుండా, బ్రౌజర్లోనే నేరుగా Modern C++ (GCC 13 / C++20) కంపైలర్లో ఈ కోడ్ను ఎగ్జిక్యూట్ చేసి రన్టైమ్ అవుట్పుట్ను తనిఖీ చేయండి.