పాలిమార్ఫిజమ్ & Virtual Functions

🌐 Modern C++ (C++20/C++17) 🟢 Chapter 16 of 20 📂 Phase 04: ఆబ్జెక్ట్ ఓరియెంటెడ్ OOP 📅 2026 Edition
📌 Covered in this chapter: Compile-time vs Run-time Polymorphism · virtual కీవర్డ్ · override & final · Pure Virtual Functions & Abstract Classes · vtable మెకానిక్స్

ఆబ్జెక్ట్ ఓరియెంటెడ్ ప్రోగ్రామింగ్ ప్రపంచంలో అత్యంత ఉత్కృష్టమైన మరియు శక్తివంతమైన ఆత్మ: పాలిమార్ఫిజమ్ (Polymorphism - బహురూపత). ఒకే ఒక సాధారణ కమాండ్‌ను పంపినప్పుడు, వేర్వేరు ఆబ్జెక్టులు వాటి స్వంత ప్రత్యేక రీతిలో ఆ కమాండ్‌ను అమలు చేయడాన్నే పాలిమార్ఫిజమ్ అంటారు. ఉదాహరణకు ఒక రిమోట్ కంట్రోలర్ నుండి "Play" బటన్ నొక్కినప్పుడు టీవీ, మ్యూజిక్ ప్లేయర్, లేదా వీడియో గేమ్ తమ తమ శైలిలో ప్లే చేయడం వంటిది.

C++ లో రన్‌టైమ్ పాలిమార్ఫిజమ్‌ను సాధించడానికి పునాది రాళ్ళు వర్చువల్ ఫంక్షన్లు (Virtual Functions). అయితే కంపైలర్ మరియు హార్డ్‌వేర్ లెవెల్‌లో రన్‌టైమ్ డిస్పాచ్ ఎలా జరుగుతుందో తెలుసుకోవడానికి ప్రఖ్యాత vtable (Virtual Method Table) మరియు vptr ల మెకానిక్స్‌ను అర్థం చేసుకోవడం తప్పనిసరి. వీటితో పాటే Modern C++11 యొక్క భద్రతా కవచాలైన override, final, మరియు మెమరీ లీక్స్‌ను నివారించే వర్చువల్ డిస్ట్రక్టర్లు (Virtual Destructors) అత్యంత కీలకమైనవి.

ఈ సమగ్ర మాస్టర్‌క్లాస్‌లో మనం Compile-time vs Run-time Polymorphism, Object Slicing ప్రమాదాలు, Pure Virtual Functions & Abstract Interfaces, vtable అంతర్గత మెమరీ ఆర్కిటెక్చర్, మరియు పూర్తి స్థాయి "Enterprise Multi-Cloud Infrastructure Provisioner & Kubernetes Orchestrator" ప్రాజెక్ట్‌ను ప్రత్యక్షంగా నిర్మించి నేర్చుకుందాం!

1 పాలిమార్ఫిజమ్ అంటే ఏమిటి? (Many Forms — The Soul of OOP)

పాలిమార్ఫిజమ్ (Polymorphism) అనే పదం గ్రీకు భాష నుండి వచ్చింది: Poly అంటే "అనేక" (Many), మరియు Morph అంటే "రూపాలు" (Forms).

సాఫ్ట్‌వేర్ ఇంజనీరింగ్‌లో: ఒకే ఒక ఉమ్మడి ఇంటర్‌ఫేస్ (Interface) ద్వారా విభిన్న రకాల ఆబ్జెక్టులను ఏకరూపంలో నియంత్రించగలగడాన్నే పాలిమార్ఫిజమ్ అంటారు.

ఒక వాస్తవ ఉదాహరణ చూద్దాం: మీ కంప్యూటర్‌లో అనేక రకాల డాక్యుమెంట్లు (PDF, Word, Excel, Image) ఉన్నాయి. మీరు వాటన్నింటినీ ప్రింట్ చేయాలనుకున్నప్పుడు వాటన్నింటికీ print() అనే ఒకే కమాండ్‌ను ఇస్తారు. కానీ PDF తన స్వంత పద్ధతిలో ప్రింట్ అవుతుంది, Word తన స్వంత ఫార్మాట్‌లో ప్రింట్ అవుతుంది. ఇదే పాలిమార్ఫిజమ్!

2 కంపైల్-టైమ్ వర్సెస్ రన్-టైమ్ పాలిమార్ఫిజమ్ (Early vs Late Binding)

C++ లో పాలిమార్ఫిజమ్ ప్రధానంగా రెండు రూపాల్లో సాధ్యమవుతుంది:

అంశం / ఫీచర్ కంపైల్-టైమ్ పాలిమార్ఫిజమ్ (Static / Early Binding) రన్-టైమ్ పాలిమార్ఫిజమ్ (Dynamic / Late Binding)
ఎలా సాధిస్తారు? Function Overloading, Operator Overloading, C++ Templates Virtual Functions మరియు Base Class Pointers / References
బైండింగ్ సమయం ప్రోగ్రామ్ కంపైల్ అయ్యే సమయంలోనే కంపైలర్ ఫంక్షన్ కాల్‌ను ఫిక్స్ చేస్తుంది ప్రోగ్రామ్ రన్ అవుతున్నప్పుడు ఆబ్జెక్ట్ రకాన్ని బట్టి డైనమిక్‌గా నిర్ణయిస్తుంది
పనితీరు (Performance) అత్యంత వేగవంతం (Zero Runtime Overhead, CPU Direct Jump) స్వల్ప ఓవర్‌హెడ్ (vtable pointer lookup ద్వారా ఇన్-డైరెక్ట్ కాల్)
సౌలభ్యం (Flexibility) రన్‌టైమ్‌లో కొత్త రకాల ప్లగిన్‌లను డైనమిక్‌గా లోడ్ చేయలేదు అత్యంత అనుకూలమైనది (రన్‌టైమ్ ప్లగ్-అండ్-ప్లే ఆర్కిటెక్చర్)

3 ఆబ్జెక్ట్ స్లైసింగ్ సమస్య (The Object Slicing Trap)

పాలిమార్ఫిజమ్ నేర్చుకునే ప్రతి ఒక్కరూ ప్రారంభంలో చేసే ఘోరమైన తప్పు: ఆబ్జెక్ట్ స్లైసింగ్ (Object Slicing).

ఒక బేస్ క్లాస్ వేరియబుల్‌కు ఒక చైల్డ్ క్లాస్ ఆబ్జెక్ట్‌ను Pass-by-Value గా అసైన్ చేసినప్పుడు:

Base b = derivedObj; // ⚠️ DANGER: Object Slicing జరిగిపోయింది!

ఇలా జరిగినప్పుడు కంపైలర్ కేవలం బేస్ క్లాస్‌కు సంబంధించిన భాగాలను మాత్రమే కాపీ చేసి, చైల్డ్ క్లాస్ యొక్క అదనపు ఫీచర్లను మెమరీలో నిర్దాక్షిణ్యంగా కత్తిరించి (Sliced off) పారేస్తుంది! ఫలితంగా పాలిమార్ఫిజమ్ పూర్తిగా నశిస్తుంది.

object_slicing_trap.cpp
#include <iostream>

class Vehicle {
public:
    virtual void describe() const {
        std::cout << "  🚗 [Vehicle] సాధారణ రవాణా వాహనం.\n";
    }
};

class SuperCar : public Vehicle {
public:
    int turboHorsepower = 850;
    void describe() const override {
        std::cout << "  🏎️ [SuperCar] టర్బో సూపర్ కార్! అశ్వశక్తి: " << turboHorsepower << " HP!\n";
    }
};

// ❌ ప్రమాదకరమైన ఫంక్షన్: Pass by Value (Object Slicing జరుగుతుంది!)
void inspectByValue(Vehicle v) {
    v.describe(); // కేవలం బేస్ వెర్షన్ మాత్రమే పిలువబడుతుంది!
}

// ✅ సరైన పాలిమార్ఫిక్ ఫంక్షన్: Pass by Reference
void inspectByReference(const Vehicle& v) {
    v.describe(); // అసలైన చైల్డ్ పాలిమార్ఫిక్ మెథడ్ రన్ అవుతుంది!
}

int main() {
    SuperCar ferrari;
    std::cout << "=== Pass by Value (స్లైసింగ్ వల్ల సూపర్ కార్ ఫీచర్లు కత్తిరించబడ్డాయి) ===\n";
    inspectByValue(ferrari);

    std::cout << "\n=== Pass by Reference (నిజమైన పాలిమార్ఫిజమ్ విజయవంతం!) ===\n";
    inspectByReference(ferrari);
    return 0;
}

4 virtual కీవర్డ్ & డైనమిక్ మెథడ్ డిస్పాచ్ (Dynamic Dispatch)

ఒక బేస్ క్లాస్ లోని ఫంక్షన్ డిక్లరేషన్ ముందు మనం virtual కీవర్డ్‌ను జోడించినప్పుడు, కంపైలర్‌కు ఒక స్పష్టమైన సందేశం వెళ్తుంది:

"ఈ ఫంక్షన్‌ను కంపైల్ చేసేటప్పుడే గుడ్డిగా బేస్ క్లాస్ అడ్రస్‌తో లింక్ చేయవద్దు! రన్‌టైమ్‌లో పాయింటర్ చూపిస్తున్న అసలైన ఆబ్జెక్ట్ రకాన్ని తనిఖీ చేసి, ఆ చైల్డ్ క్లాస్ ఫంక్షన్‌నే పిలవండి!"
virtual_function_basics.cpp
#include <iostream>
#include <memory>

class PaymentGateway {
public:
    virtual void processPayment(double amount) {
        std::cout << "  💳 [బేస్ గేట్‌వే] సాధారణ చెల్లింపు ప్రాసెస్ అవుతోంది: ₹ " << amount << "\n";
    }

    virtual ~PaymentGateway() = default;
};

class UPIPayment : public PaymentGateway {
public:
    void processPayment(double amount) override {
        std::cout << "  📱 [UPI గేట్‌వే] NPCI సర్వర్ ద్వారా తక్షణ UPI చెల్లింపు: ₹ " << amount << "\n";
    }
};

class CreditCardPayment : public PaymentGateway {
public:
    void processPayment(double amount) override {
        std::cout << "  💳 [క్రెడిట్ కార్డ్] Visa/Mastercard 3D-Secure OTP ప్రాసెస్: ₹ " << amount << "\n";
    }
};

void executeTransaction(PaymentGateway* gateway, double amount) {
    gateway->processPayment(amount);
}

int main() {
    std::cout << "===== C++ Virtual Functions Polymorphism =====\n";
    UPIPayment upi;
    CreditCardPayment card;

    executeTransaction(&upi, 1500.0);  // UPI మెథడ్ కాల్ అవుతుంది
    executeTransaction(&card, 4500.0); // Credit Card మెథడ్ కాల్ అవుతుంది
    return 0;
}

5 Modern C++ override & final Specifiers (C++11 Guardrails)

సాంప్రదాయ C++98 లో వర్చువల్ ఫంక్షన్లను ఓవర్‌రైడ్ చేసేటప్పుడు ఒక చిన్న టైపో (ఉదాహరణకు బేస్ లో const ఉండి చైల్డ్ లో లేకపోవడం) జరిగినా కంపైలర్ సైలెంట్‌గా ఒక కొత్త ఫంక్షన్‌ను సృష్టించి ఓవర్‌రైడింగ్‌ను విఫలం చేసేది.

దీనిని అరికట్టడానికి Modern C++11 లో override మరియు final కీవర్డ్లు ప్రవేశపెట్టబడ్డాయి:

override_final_guardrails.cpp
#include <iostream>

class BaseLogger {
public:
    virtual void log(const std::string& msg) {
        std::cout << "[BaseLog]: " << msg << "\n";
    }
    virtual ~BaseLogger() = default;
};

class ConsoleLogger : public BaseLogger {
public:
    // override కీవర్డ్ కంపైలర్ చేత సిగ్నేచర్‌ను ఖచ్చితంగా వెరిఫై చేయిస్తుంది!
    void log(const std::string& msg) override {
        std::cout << "🖥️ [Console]: " << msg << "\n";
    }
};

// final క్లాస్: దీనిని ఇక ఎవరూ ఇన్హెరిట్ చేసుకోలేరు!
class SecureAuditor final : public BaseLogger {
public:
    // final మెథడ్: దీనిని చైల్డ్ క్లాసులు ఓవర్‌రైడ్ చేయలేవు
    void log(const std::string& msg) override final {
        std::cout << "🔒 [SHA-256 Secure Audit Log]: " << msg << "\n";
    }
};

int main() {
    ConsoleLogger cLog;
    SecureAuditor sLog;

    BaseLogger* p1 = &cLog;
    BaseLogger* p2 = &sLog;

    p1->log("User logged in");
    p2->log("Admin accessed ledger");
    return 0;
}

6 ప్యూర్ వర్చువల్ ఫంక్షన్లు (= 0) & అబ్‌స్ట్రాక్ట్ క్లాసెస్ (Abstract Interfaces)

ఒక బేస్ క్లాస్ లో ఫంక్షన్‌కు ఎటువంటి బాడీని రాయకుండా, కేవలం = 0; అని రాసి వదిలేస్తే దానిని ప్యూర్ వర్చువల్ ఫంక్షన్ (Pure Virtual Function) అంటారు.

కనీసం ఒక్క ప్యూర్ వర్చువల్ ఫంక్షన్ కలిగిన క్లాస్‌ను అబ్‌స్ట్రాక్ట్ క్లాస్ (Abstract Class) అంటారు. దీనికి డైరెక్ట్ ఆబ్జెక్టులను సృష్టించలేము.

abstract_interface_contract.cpp
#include <iostream>
#include <vector>

// అబ్‌స్ట్రాక్ట్ ఇంటర్‌ఫేస్ (కాంట్రాక్ట్)
class AudioCodec {
public:
    virtual void decodePacket(const std::string& rawBytes) = 0; // Pure Virtual!
    virtual void encodePacket() = 0;                             // Pure Virtual!
    virtual ~AudioCodec() = default;
};

class MP3Codec : public AudioCodec {
public:
    void decodePacket(const std::string& rawBytes) override {
        std::cout << "  🎵 [MP3 డీకోడర్] MPEG-1 Layer III ఫ్రేమ్ ప్రాసెస్ అయ్యింది.\n";
    }
    void encodePacket() override {
        std::cout << "  🎵 [MP3 ఎన్‌కోడర్] 320 kbps ఆడియో కంప్రెషన్ పూర్తయింది.\n";
    }
};

class FLACCodec : public AudioCodec {
public:
    void decodePacket(const std::string& rawBytes) override {
        std::cout << "  🎧 [FLAC డీకోడర్] లాస్‌లెస్ 24-bit 192kHz హై-రెస్ ఆడియో ప్లేబ్యాక్.\n";
    }
    void encodePacket() override {
        std::cout << "  🎧 [FLAC ఎన్‌కోడర్] జీరో క్వాలిటీ లాస్ కంప్రెషన్.\n";
    }
};

int main() {
    // AudioCodec codec; // ❌ కంపైలర్ ఎర్రర్! అబ్‌స్ట్రాక్ట్ క్లాస్ కు ఆబ్జెక్ట్ సృష్టించలేము!
    MP3Codec mp3;
    FLACCodec flac;

    AudioCodec* player = &flac;
    player->decodePacket("0xFFE3_PCM_DATA");
    return 0;
}

7 అండర్ ది హుడ్: vtable & vptr అంతర్గత మెకానిక్స్

సిస్టమ్స్ ప్రోగ్రామింగ్ ఇంటర్వ్యూలలో అత్యంత తరచుగా అడిగే లోతైన ప్రశ్న: "C++ లో పాలిమార్ఫిజమ్ హార్డ్‌వేర్ మరియు మెమరీ స్థాయిలో నిజంగా ఎలా పనిచేస్తుంది?"

[The Mechanics of vptr and vtable in RAM]
RAM Object Memory (Derived)          Static Memory (vtable in Text/Data)
+----------------------------+         +-----------------------------------+
| vptr (Hidden 8-Byte Ptr) |-------->| Index [0]: &Derived::render() |
+----------------------------+         | Index [1]: &Derived::calculate() |
| int memberData1 |         +-----------------------------------+
| double memberData2 |
+----------------------------+
  1. vtable: ఫంక్షన్ పాయింటర్ల స్టాటిక్ అర్రే. ప్రతి పాలిమార్ఫిక్ క్లాస్‌కు ఒకటే ఉంటుంది.
  2. vptr: ప్రతి ఆబ్జెక్ట్ మెమరీ ప్రారంభంలో ఉండే 8-బైట్ల పాయింటర్. ఇది సంబంధిత vtable ను పాయింట్ చేస్తుంది.
  3. Dynamic Dispatch: ptr->func() అన్నప్పుడు vptr ద్వారా vtable లోని ఇండెక్స్‌ను యాక్సెస్ చేసి జంప్ చేస్తుంది.

8 వర్చువల్ డిస్ట్రక్టర్లు (Virtual Destructors: The Life-Saving Rule)

బేస్ పాయింటర్ ద్వారా చైల్డ్ ఆబ్జెక్ట్‌ను డిలీట్ చేసినప్పుడు చైల్డ్ డిస్ట్రక్టర్ కూడా సరిగ్గా కాల్ అయ్యి మెమరీ లీక్ కాకుండా చూసుకోవడానికి బేస్ డిస్ట్రక్టర్ తప్పనిసరిగా virtual అయి ఉండాలి.

virtual_destructor_leak_demo.cpp
#include <iostream>

class BaseResource {
public:
    BaseResource() { std::cout << "  [Base] రిసోర్స్ కేటాయించబడింది.\n"; }
    // 💡 వర్చువల్ డిస్ట్రక్టర్ లేకపోతే చైల్డ్ మెమరీ శాశ్వతంగా లీక్ అవుతుంది!
    virtual ~BaseResource() { std::cout << "  [Base] రిసోర్స్ సురక్షితంగా క్లీన్ అయింది.\n"; }
};

class HeavyDerived : public BaseResource {
private:
    int* heapBuffer;
public:
    HeavyDerived() : heapBuffer(new int[5000]) {
        std::cout << "  [Derived] 20,000 బైట్ల హీప్ మెమరీ కేటాయించబడింది.\n";
    }
    ~HeavyDerived() override {
        std::cout << "  [Derived] హీప్ బఫర్ లీక్ కాకుండా డిలీట్ చేయబడింది!\n";
        delete[] heapBuffer;
    }
};

int main() {
    std::cout << "===== వర్చువల్ డిస్ట్రక్టర్ లైఫ్‌సైకిల్ పరీక్ష =====\n";
    BaseResource* ptr = new HeavyDerived();

    // delete ptr పిలిచినప్పుడు:
    // 1. ముందుగా HeavyDerived డిస్ట్రక్టర్ కాల్ అవుతుంది
    // 2. తర్వాత BaseResource డిస్ట్రక్టర్ కాల్ అవుతుంది
    delete ptr;

    std::cout << "మెమరీ లీక్ లేకుండా క్లీనప్ విజయవంతమైంది!\n";
    return 0;
}

9 పాలిమార్ఫిక్ కాస్టింగ్: dynamic_cast vs static_cast

ఒక బేస్ పాయింటర్ చూపిస్తున్న ఆబ్జెక్ట్ నిజంగా నిర్దిష్ట చైల్డ్ క్లాస్ అవునా కాదా అని రన్‌టైమ్‌లో తనిఖీ చేసి సురక్షితంగా మార్చడానికి dynamic_cast ను ఉపయోగిస్తాం.

dynamic_cast_safe_downcast.cpp
#include <iostream>

class Animal {
public:
    virtual void speak() const = 0;
    virtual ~Animal() = default;
};

class Dog : public Animal {
public:
    void speak() const override { std::cout << "  🐶 బౌ బౌ!\n"; }
    void fetchBall() const { std::cout << "  🎾 కుక్క బంతిని తెచ్చింది!\n"; }
};

class Cat : public Animal {
public:
    void speak() const override { std::cout << "  🐱 మియావ్!\n"; }
};

void identifyAndPlay(Animal* a) {
    a->speak(); // పాలిమార్ఫిక్ కాల్

    // సురక్షిత డౌన్‌కాస్టింగ్: ఇది కుక్క అయితేనే బంతిని ఆడుతుంది!
    Dog* dogPtr = dynamic_cast<Dog*>(a);
    if (dogPtr != nullptr) {
        dogPtr->fetchBall();
    } else {
        std::cout << "  ℹ️ ఇది కుక్క కాదు, బంతి తీసుకురాదు.\n";
    }
}

int main() {
    Dog myDog;
    Cat myCat;

    identifyAndPlay(&myDog);
    identifyAndPlay(&myCat);
    return 0;
}

10 పాలిమార్ఫిజమ్ యొక్క పెర్ఫార్మెన్స్ కాస్ట్ & ఆప్టిమైజేషన్

హై-ఫ్రీక్వెన్సీ ట్రేడింగ్ (HFT) మరియు గేమ్ ఇంజిన్లలో వర్చువల్ ఫంక్షన్లను వాడేటప్పుడు క్రింది మూడు పెర్ఫార్మెన్స్ అంశాలను పరిగణించాలి:

  1. మెమరీ ఓవర్‌హెడ్: ప్రతి ఆబ్జెక్ట్‌కు 8 బైట్ల vptr అదనంగా చేరుతుంది.
  2. ఇన్‌డైరెక్షన్ ఓవర్‌హెడ్: డైరెక్ట్ ఫంక్షన్ కాల్ కంటే vtable ద్వారా వెళ్లడం వల్ల CPU లో 2-3 అదనపు సైకిళ్లు పడుతుంది.
  3. Inlining పరిమితి: కంపైలర్ వర్చువల్ ఫంక్షన్లను ఇన్‌లైన్ (Inline) చేయలేదు.

11 కన్‌స్ట్రక్టర్లలో వర్చువల్ ఫంక్షన్ల పిలుపు తప్పు (The Constructor Trap)

గోల్డెన్ రూల్: కన్‌స్ట్రక్టర్ లేదా డిస్ట్రక్టర్ లోపల ఎప్పుడూ వర్చువల్ ఫంక్షన్లను పిలవకూడదు!

ఎందుకు? ఎందుకంటే బేస్ క్లాస్ కన్‌స్ట్రక్టర్ రన్ అవుతున్న సమయంలో చైల్డ్ క్లాస్ ఇంకా పుట్టనేలేదు (దాని vtable పాయింటర్ ఇంకా లోడ్ కాలేదు). ఆ సమయంలో వర్చువల్ ఫంక్షన్ పిలిస్తే బేస్ ఫంక్షన్ మాత్రమే రన్ అవుతుంది తప్ప చైల్డ్ ఫంక్షన్ రన్ కాదు!

12 రియల్-వరల్డ్ ప్రాజెక్ట్: Enterprise Multi-Cloud Infrastructure Provisioner & Orchestrator

నిజ జీవితంలో ఆధునిక ఎంటర్‌ప్రైజ్ క్లౌడ్ ప్లాట్‌ఫామ్‌లు (Terraform, Pulumi వంటివి) ఏకకాలంలో AWS, Google Cloud, మరియు Microsoft Azure వంటి విభిన్న క్లౌడ్ ప్రొవైడర్లలో వర్చువల్ మెషీన్లు, కుబెర్‌నెటీస్ క్లస్టర్లు మరియు డేటాబేస్‌లను డిప్లాయ్ చేయాలి.

ఈ ప్రాజెక్ట్‌లో మనం అబ్‌స్ట్రాక్ట్ బేస్ క్లాస్, ప్యూర్ వర్చువల్ ఫంక్షన్లు, వర్చువల్ డిస్ట్రక్టర్లు మరియు std::unique_ptr పాలిమార్ఫిక్ వెక్టార్‌తో కూడిన ఎంటర్‌ప్రైజ్ మల్టీ-క్లౌడ్ ఆర్కెస్ట్రేషన్ ఇంజిన్ ను నిర్మిస్తున్నాం:

MultiCloudOrchestrator.cpp
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <iomanip>

// అబ్‌స్ట్రాక్ట్ బేస్ ఇంటర్‌ఫేస్ (Abstract Base Class)
class CloudProvider {
protected:
    std::string providerName;
    std::string region;

public:
    CloudProvider(std::string name, std::string reg) : providerName(name), region(reg) {}

    virtual ~CloudProvider() {
        std::cout << "  🗑️ [CloudProvider Destructor] " << providerName << " రిసోర్సులు క్లీన్ చేయబడ్డాయి.\n";
    }

    virtual void provisionComputeInstance(const std::string& instanceType, int count) = 0;
    virtual void deployKubernetesCluster(const std::string& clusterName, int nodes) = 0;
    virtual double calculateEstimatedHourlyCost() const = 0;

    std::string getProviderName() const { return providerName; }
};

class AWSProvider : public CloudProvider {
public:
    AWSProvider(std::string reg) : CloudProvider("Amazon Web Services (AWS)", reg) {}

    void provisionComputeInstance(const std::string& instanceType, int count) override {
        std::cout << "  ☁️ [AWS EC2] " << count << "x " << instanceType << " ఇన్స్టాన్స్‌లు " << region << " లో లాంచ్ అయ్యాయి!\n";
    }

    void deployKubernetesCluster(const std::string& clusterName, int nodes) override {
        std::cout << "  ☸️ [AWS EKS] అమెజాన్ ఎలాస్టిక్ కుబెర్‌నెటీస్ సర్వీస్: " << clusterName << " (" << nodes << " Worker Nodes)\n";
    }

    double calculateEstimatedHourlyCost() const override {
        return 12.50;
    }
};

class GCPProvider : public CloudProvider {
public:
    GCPProvider(std::string reg) : CloudProvider("Google Cloud Platform (GCP)", reg) {}

    void provisionComputeInstance(const std::string& instanceType, int count) override {
        std::cout << "  🌐 [GCP Compute Engine] " << count << "x " << instanceType << " VM లు " << region << " జోన్‌లో ప్రారంభమయ్యాయి!\n";
    }

    void deployKubernetesCluster(const std::string& clusterName, int nodes) override {
        std::cout << "  ☸️ [Google GKE] ఆటోపైలట్ కుబెర్‌నెటీస్ క్లస్టర్: " << clusterName << " (" << nodes << " Compute Nodes)\n";
    }

    double calculateEstimatedHourlyCost() const override {
        return 10.80;
    }
};

class AzureProvider : public CloudProvider {
public:
    AzureProvider(std::string reg) : CloudProvider("Microsoft Azure", reg) {}

    void provisionComputeInstance(const std::string& instanceType, int count) override {
        std::cout << "  🔷 [Azure Virtual Machines] " << count << "x " << instanceType << " VM లు " << region << " లో సిద్ధమయ్యాయి!\n";
    }

    void deployKubernetesCluster(const std::string& clusterName, int nodes) override {
        std::cout << "  ☸️ [Azure AKS] అజూర్ కుబెర్‌నెటీస్ సర్వీస్ క్లస్టర్: " << clusterName << " (" << nodes << " Nodes)\n";
    }

    double calculateEstimatedHourlyCost() const override {
        return 11.75;
    }
};

int main() {
    std::cout << "=======================================================================\n";
    std::cout << "🚀 [ENTERPRISE MULTI-CLOUD ORCHESTRATION & DEPLOYMENT ENGINE]\n";
    std::cout << "=======================================================================\n";

    std::vector<std::unique_ptr<CloudProvider>> cloudFleet;

    cloudFleet.push_back(std::make_unique<AWSProvider>("ap-south-1 (Mumbai)"));
    cloudFleet.push_back(std::make_unique<GCPProvider>("asia-south1 (Delhi)"));
    cloudFleet.push_back(std::make_unique<AzureProvider>("central-india (Pune)"));

    double totalFleetHourlyCost = 0.0;

    std::cout << "\n[మల్టీ-క్లౌడ్ డిప్లాయ్‌మెంట్ ఆటోమేషన్ రన్ అవుతోంది]:\n\n";
    for (const auto& provider : cloudFleet) {
        std::cout << ">>> ఆర్కెస్ట్రేషన్ ప్రొవైడర్: " << provider->getProviderName() << "\n";
        provider->provisionComputeInstance("m5.2xlarge", 4);
        provider->deployKubernetesCluster("prod-banking-mesh", 8);

        double cost = provider->calculateEstimatedHourlyCost();
        totalFleetHourlyCost += cost;
        std::cout << "    అంచనా గంట ఖర్చు: $ " << std::fixed << std::setprecision(2) << cost << "\n\n";
    }

    std::cout << "=======================================================================\n";
    std::cout << "💰 మొత్తం మల్టీ-క్లౌడ్ నెట్‌వర్క్ గంట ఖర్చు: $ " << totalFleetHourlyCost << " / Hour\n";
    std::cout << "=======================================================================\n";
    std::cout << "ప్రోగ్రామ్ ముగింపు: వర్చువల్ డిస్ట్రక్టర్లు అన్ని క్లౌడ్ రిసోర్సులను సురక్షితంగా క్లీన్ చేస్తాయి!\n";
    return 0;
}

13 సారాంశం & ఇంటరాక్టివ్ క్విజ్ (Summary & Self-Check Quizzes)

📌 ఈ అధ్యాయంలో నేర్చుకున్న ప్రధాన అంశాలు:

  • Polymorphism: ఒకే సాధారణ ఇంటర్‌ఫేస్ ద్వారా అనేక విభిన్న రకాల ఆబ్జెక్టులను ఏకరూపంలో నియంత్రించే సామర్థ్యం.
  • Compile-time vs Run-time: ఫంక్షన్ ఓవర్‌లోడింగ్ కంపైల్-టైమ్‌లో బైండ్ అవుతుంది; వర్చువల్ ఫంక్షన్లు రన్‌టైమ్‌లో డైనమిక్‌గా బైండ్ అవుతాయి.
  • Object Slicing: బేస్ వేరియబుల్‌కు పాస్ చేసినప్పుడు చైల్డ్ డేటా కత్తిరించబడుతుంది; దీన్ని నివారించడానికి ఎల్లప్పుడూ Base* లేదా Base& వాడాలి.
  • virtual Keyword: కంపైలర్‌కు డైనమిక్ డిస్పాచ్ చేయమని ఆదేశించే కీవర్డ్.
  • override & final: C++11 సేఫ్‌గార్డ్స్. స్పెల్లింగ్ పొరపాట్లను override నివారిస్తుంది, మరింత ఓవర్‌రైడింగ్‌ను final అడ్డుకుంటుంది.
  • Pure Virtual & Abstract: virtual void f() = 0; ఉంటే అది అబ్‌స్ట్రాక్ట్ క్లాస్. దీనికి ఆబ్జెక్టులు ఉండవు, కేవలం కాంట్రాక్ట్ మాత్రమే.
  • vtable & vptr: వర్చువల్ ఫంక్షన్లను రన్‌టైమ్‌లో పాయింట్ చేయడానికి కంపైలర్ ఉపయోగించే ఫంక్షన్ పాయింటర్ టేబుల్ మరియు ఆబ్జెక్ట్ పాయింటర్.
  • Virtual Destructors: బేస్ పాయింటర్ ద్వారా ఆబ్జెక్ట్‌ను డిలీట్ చేసినప్పుడు చైల్డ్ మెమరీ లీక్ కాకుండా ఉండేలా చూసే పవిత్ర నియమం.

🧠 మీ అవగాహనను పరీక్షించుకోండి (5 Interactive Quizzes):

ప్రశ్న 1: C++ లో ఒక బేస్ క్లాస్‌లోని డిస్ట్రక్టర్‌ను virtual గా డిక్లేర్ చేయకపోతే ఏ ప్రమాదం జరుగుతుంది?
సమాధానం: చైల్డ్ క్లాస్ మెమరీ లీక్ (Memory Leak) అవుతుంది!
వివరణ: Base* ptr = new Derived(); delete ptr; చేసినప్పుడు, బేస్ డిస్ట్రక్టర్ వర్చువల్ కాకపోతే కేవలం బేస్ క్లాస్ డిస్ట్రక్టర్ మాత్రమే కాల్ అవుతుంది; చైల్డ్ క్లాస్ డిస్ట్రక్టర్ ఎప్పటికీ ఎగ్జిక్యూట్ కాదు, ఫలితంగా చైల్డ్ కేటాయించిన రిసోర్సులు లీక్ అయిపోతాయి.
ప్రశ్న 2: Object Slicing అంటే ఏమిటి? దానిని ఎలా నివారించవచ్చు?
సమాధానం: చైల్డ్ ఆబ్జెక్ట్‌ను బేస్ వేరియబుల్‌కు Pass-by-Value గా ఇచ్చినప్పుడు చైల్డ్ మెంబర్లు కత్తిరించబడటం. నివారణకు Base పాయింటర్లు (Base*) లేదా రిఫరెన్సులు (Base&) వాడాలి!
వివరణ: బేస్ వేరియబుల్‌కు చైల్డ్ ఆబ్జెక్ట్ సైజు పట్టదు. కాబట్టి బేస్ భాగం మాత్రమే కాపీ అవుతుంది, చైల్డ్ భాగాలు నశిస్తాయి.
ప్రశ్న 3: C++11 లో ఫంక్షన్ పక్కన override కీవర్డ్ రాయడం ఎందుకు తప్పనిసరి బెస్ట్ ప్రాక్టీస్?
సమాధానం: స్పెల్లింగ్ తప్పులు లేదా సిగ్నేచర్ మిస్‌మ్యాచ్ వల్ల జరిగే బగ్స్‌ను కంపైల్-టైమ్‌లోనే పసిగట్టడానికి!
వివరణ: override రాసినప్పుడు, బేస్ క్లాస్‌లో సరిగ్గా అదే సంతకంతో వర్చువల్ ఫంక్షన్ లేకపోతే కంపైలర్ ఎర్రర్ ఇస్తుంది. ఇది రన్‌టైమ్‌లో అనుకోని నిశ్శబ్ద వైఫల్యాలను నివారిస్తుంది.
ప్రశ్న 4: 64-bit ఆర్కిటెక్చర్‌లో వర్చువల్ ఫంక్షన్లు ఉన్న క్లాస్ యొక్క ఆబ్జెక్ట్ సైజు ఎందుకు అదనంగా 8 బైట్లు పెరుగుతుంది?
సమాధానం: కంపైలర్ చేర్చే హిడెన్ vptr (Virtual Table Pointer) కొరకు!
వివరణ: వర్చువల్ ఫంక్షన్లు ఉన్న ప్రతి ఆబ్జెక్ట్ ప్రారంభంలో కంపైలర్ ఒక 8-బైట్ల vptr ను చొప్పిస్తుంది. ఇది ఆ క్లాస్ యొక్క vtable ను పాయింట్ చేసి రన్‌టైమ్ డిస్పాచ్‌ను సాధ్యం చేస్తుంది.
ప్రశ్న 5: కన్‌స్ట్రక్టర్ లేదా డిస్ట్రక్టర్ లోపల వర్చువల్ ఫంక్షన్లను ఎందుకు పిలవకూడదు?
సమాధానం: ఎందుకంటే ఆ సమయంలో పాలిమార్ఫిజమ్ పనిచేయదు (చైల్డ్ వెర్షన్ కాల్ అవ్వదు)!
వివరణ: బేస్ కన్‌స్ట్రక్టర్ రన్ అవుతున్న సమయంలో చైల్డ్ ఆబ్జెక్ట్ ఇంకా పుట్టలేదు (అసంపూర్ణం); డిస్ట్రక్టర్ సమయంలో చైల్డ్ ముందే నశించిపోయింది. కాబట్టి కంపైలర్ వర్చువల్ డిస్పాచ్ చేయకుండా బేస్ క్లాస్ వెర్షన్‌ను మాత్రమే పిలుస్తుంది.
← మునుపటి అధ్యాయం: 15. ఇన్హెరిటెన్స్ తర్వాతి అధ్యాయం: 17. ఆపరేటర్ ఓవర్‌లోడింగ్ →

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

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