ఫంక్షన్స్ & Function Overloading

🌐 Modern C++ (C++20/C++17) 🟢 Chapter 9 of 20 📂 Phase 03: ఫంక్షన్స్, మెమరీ & పాయింటర్లు 📅 2026 Edition
📌 Covered in this chapter: డిక్లరేషన్ & డెఫినిషన్ · Pass by Value vs Pass by Reference (&) · Default Arguments · Function Overloading · Inline Functions

ఒక పెద్ద సాఫ్ట్‌వేర్ అప్లికేషన్‌లో వేలాది లైన్ల కోడ్ ఉంటుంది. ఆ కోడ్ మొత్తాన్ని ఒకే main() ఫంక్షన్‌లో రాసుకుంటూ పోతే, అది చదవడానికి అసాధ్యమైన గందరగోళ మోనోలిత్‌గా మారిపోతుంది. సాఫ్ట్‌వేర్ ఇంజనీరింగ్‌లో అత్యంత కీలకమైన ఆర్కిటెక్చర్ సూత్రం మాడ్యులరైజేషన్ (Modular Programming) — అంటే ఒక పెద్ద సమస్యను స్వతంత్రమైన చిన్న చిన్న భాగాలుగా విభజించడం.

ఆ స్వతంత్ర విభాగాలనే మనం ఫంక్షన్స్ (Functions) అంటాం. ఈ సమగ్ర మాస్టర్‌క్లాస్‌లో మనం:

1 ఫంక్షన్స్ అంటే ఏమిటి? మాడ్యులర్ ప్రోగ్రామింగ్ & Code Reusability

ఒక నిర్దిష్టమైన పనిని (Specific Task) పూర్తి చేయడానికి రూపొందించబడిన స్వయంప్రతిపత్తి గల కోడ్ బ్లాక్‌ను ఫంక్షన్ (Function) అంటారు.

సాఫ్ట్‌వేర్ పరిశ్రమలో ఫంక్షన్స్ ఎందుకు ప్రాణాధారమైనవి?

  • Code Reusability (కోడ్ పునర్వినియోగం): ఒకే లాజిక్‌ను (ఉదా: జిఎస్‌టి పన్ను లెక్కించడం) ప్రోగ్రామ్‌లో పది చోట్ల రాయకుండా, ఒక ఫంక్షన్‌గా రాసి ఎన్నిసార్లైనా పిలుచుకోవచ్చు (Call).
  • Single Responsibility Principle (SRP): ప్రతి ఫంక్షన్ ఒకే ఒక్క పనిని పరిపూర్ణంగా చేయాలి. దీనివల్ల డీబగ్గింగ్ చేయడం చాలా సులభమవుతుంది.
  • Abstraction (అబ్‌స్ట్రాక్షన్): ఫంక్షన్‌ను వాడేవారికి అది లోపల ఎలా పనిచేస్తుందో తెలియాల్సిన అవసరం లేదు; ఇన్పుట్ ఏమిటి మరియు అవుట్‌పుట్ ఏమి వస్తుందో తెలిస్తే చాలు (ఉదా: std::sqrt(25)).

🧩 ఒక ఫంక్షన్ యొక్క 4 ముఖ్యమైన భాగాలు

[Return Type] [Function Name] ( [Parameter List] ) {
    // ఫంక్షన్ బాడీ: వ్యాపార లాజిక్
    return [ఫలితం];
}

2 ఫంక్షన్ డిక్లరేషన్ (Prototype) vs డెఫినిషన్ (Definition)

C++ కంపైలర్ ఒక ఫైల్‌ను పై నుండి క్రిందికి (Top-to-Bottom) ఒకే పాస్‌లో చదువుతుంది. మీరు main() ఫంక్షన్ కింద ఒక ఫంక్షన్‌ను రాసి, దాన్ని main() లోపల పిలిస్తే — కంపైలర్ "error: identifier not found" అని ప్రోగ్రామ్‌ను తిరస్కరిస్తుంది!

ఈ సమస్యను పరిష్కరించడానికి C++ లో రెండు దశలు ఉన్నాయి:

  • 1. ఫంక్షన్ డిక్లరేషన్ (Function Prototype): main() కంటే ముందే కంపైలర్‌కు ఫంక్షన్ పేరు, రిటర్న్ టైప్, మరియు పారామీటర్లను పరిచయం చేయడం. ఇది కేవలం ఒక హామీ పత్రం లాంటిది (సెమికోలన్ ; తో ముగుస్తుంది).
  • 2. ఫంక్షన్ డెఫినిషన్ (Function Definition): ఫంక్షన్ లోపల అసలు కోడ్ ఏమి చేయాలో కర్లీ బ్రాకెట్లలో { ... } పూర్తిగా రాయడం.
💻 Example 1: Function Declaration vs Definition Separation
C++17
#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) వ్యవహరిస్తుంది. ఫంక్షన్ లోపల చేసే ప్రతి మార్పూ నేరుగా కాలర్ యొక్క వేరియబుల్‌ను ప్రభావితం చేస్తుంది!

💻 Example 2: Classic Variable Swap using Pass by Reference
C++17 Reference Swap
#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& లిటరల్స్ మరియు తాత్కాలిక వస్తువులను కూడా సంతోషంగా స్వీకరిస్తుంది!

💻 Example 3: Enterprise Logging with const std::string&
Modern C++ Golden Rule
#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); (తప్పు!)

💻 Example 4: Default Arguments in Banking Loan EMI Calculator
C++17
#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() రాస్తే కంపైలర్ తీవ్రమైన అంబిగ్యుటీ ఎర్రర్ ఇస్తుంది.

💻 Example 5: Function Overloading in Area Calculations
C++17 Function Overloading
#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)        ➔ _Z13calculateAreai
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. ఇది సంక్లిష్టమైన టెంప్లేట్ మెటాప్రోగ్రామింగ్‌లో ఆటోమేటిక్ టైప్ డిడక్షన్ కోసం చాలా ఉపయోగపడుతుంది.
  • constexpr Functions: ఇన్పుట్ విలువలు కంపైల్-టైమ్ స్థిరరాశులు అయితే, ఆ ఫంక్షన్‌ను ప్రోగ్రామ్ రన్ అవ్వకముందే, కంపైలేషన్ సమయంలోనే లెక్కించి స్థిర సంఖ్యగా మార్చేస్తుంది (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 సాధారణ బిగినర్ తప్పులు, బగ్స్ & అంబిగ్యుటీ ట్రాప్స్

❌ Trap 1: లోకల్ వేరియబుల్ యొక్క రెఫరెన్స్‌ను రిటర్న్ చేసే ఘోరమైన బగ్ (Dangling Reference)
int& getNumber() {
    int localVal = 100;
    return localVal; // ⚠️ ఘోరమైన తప్పు! ఫంక్షన్ ముగియగానే localVal నాశనమైపోతుంది!
} // బయట ఆ రెఫరెన్స్‌ను వాడితే క్రాష్ లేదా గార్బేజ్ వాల్యూ వస్తుంది (Dangling Reference)!
❌ Trap 2: Default Arguments మరియు Overloading మధ్య కంపైలర్ అంబిగ్యుటీ
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" ప్రాజెక్ట్‌ను రన్ చేద్దాం:

💻 Complete Masterclass Practice Project: Corporate Payroll Engine
C++17 / C++20 Complete Project
#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&' పారామీటర్ పాసింగ్‌ను ఎందుకు గోల్డెన్ ప్రామాణికంగా పరిగణిస్తారు?
సమాధానం: ఇది రెండు అద్భుతమైన ప్రయోజనాలను ఏకకాలంలో అందిస్తుంది: 1. రెఫరెన్స్ (&) ఉండటం వల్ల అసలు ఆబ్జెక్ట్ కాపీ అవ్వదు (Zero Copy Performance). 2. const ఉండటం వల్ల ఫంక్షన్ లోపల డేటా అనుకోకుండా మారకుండా రక్షణ లభిస్తుంది (Read-Only Safety) మరియు ఇది లిటరల్స్ లేదా టెంపరరీ ఆబ్జెక్టులను కూడా పారామీటర్లుగా స్వీకరించగలదు.
ప్రశ్న 3: నేమ్ మ్యాంగ్లింగ్ (Name Mangling) అంటే ఏమిటి? C++ లో ఇది ఎందుకు జరుగుతుంది?
సమాధానం: C++ లో ఫంక్షన్ ఓవర్‌లోడింగ్ సాధ్యం కావడానికి, కంపైలర్ అసెంబ్లీ కోడ్ తయారుచేసేటప్పుడు ఫంక్షన్ పేరుతో పాటు దాని పారామీటర్ల సమాచారాన్ని మిళితం చేసి ఒక ప్రత్యేకమైన పేరును (Mangled Name) సృష్టిస్తుంది. దీనివల్ల ఒకే పేరు గల బహుళ ఫంక్షన్లకు లింకర్ స్థాయిలో వేర్వేరు పేర్లు లభించి సరిగ్గా లింక్ అవుతాయి.
ప్రశ్న 4: ఇన్‌లైన్ ఫంక్షన్ (inline) CPU పెర్ఫార్మెన్స్‌ను ఎలా మెరుగుపరుస్తుంది? ఎప్పుడు ఇన్-లైన్ చేయకూడదు?
సమాధానం: inline ఫంక్షన్‌ను పిలిచినప్పుడు ఫంక్షన్ జంప్ మరియు స్టాక్ ఫ్రేమ్ క్రియేషన్ లేకుండా, నేరుగా ఆ కోడ్‌నే అక్కడ రీప్లేస్ చేస్తుంది, దీనివల్ల ఫంక్షన్ కాల్ ఓవర్‌హెడ్ తప్పుతుంది. అయితే చాలా పెద్ద ఫంక్షన్లను లేదా లూప్‌లు ఉన్నవాటిని ఇన్-లైన్ చేస్తే ఎగ్జిక్యూటబుల్ ఫైల్ సైజు విపరీతంగా పెరిగిపోయి (Code Bloat) CPU ఇన్‌స్ట్రక్షన్ క్యాష్ మిస్‌లకు దారితీస్తుంది.
ప్రశ్న 5: లోకల్ వేరియబుల్‌కు రెఫరెన్స్ (int&) రిటర్న్ చేస్తే ఏమవుతుంది? దానిని ఎలా సరిచేయాలి?
సమాధానం: ఫంక్షన్ ముగియగానే దాని లోకల్ వేరియబుల్స్ ఉన్న స్టాక్ ఫ్రేమ్ నాశనమైపోతుంది. నాశనమైన మెమరీ లొకేషన్‌కు రెఫరెన్స్ ఇవ్వడాన్ని Dangling Reference అంటారు. బయట ఆ వేరియబుల్‌ను రీడ్ చేస్తే గార్బేజ్ వాల్యూ లేదా సెగ్మెంటేషన్ ఫాల్ట్ క్రాష్ వస్తుంది. దీనిని నివారించడానికి సాధారణ విలువను (Pass by Value) రిటర్న్ చేయాలి లేదా డైనమిక్ మెమరీ/స్టాటిక్ వేరియబుల్ వాడాలి.
← మునుపటి అధ్యాయం: Chapter 08: break, continue & లూప్ కంట్రోల్
తదుపరి అధ్యాయం: Chapter 10: అర్రేలు & std::string →

ఈ ప్రాజెక్ట్‌ను లైవ్‌గా మన కంపైలర్‌లో రన్ చేయండి!

ఎటువంటి లోకల్ సెటప్ లేకుండా, బ్రౌజర్‌లోనే నేరుగా Modern C++ (GCC 13 / C++20) కంపైలర్‌లో ఈ కోడ్‌ను ఎగ్జిక్యూట్ చేసి రన్‌టైమ్ అవుట్‌పుట్‌ను తనిఖీ చేయండి.