// virtual.cpp - Métodos virtuales y no virtuales
#include <iostream>
using namespace std;

class CB
{
  public:
    virtual void mVirtual1(); // método virtual
    void mNoVirtual();        // método no virtual
};
void CB::mVirtual1()
{
  cout << "método virtual 1 en CB\n";
}
void CB::mNoVirtual()
{
  cout << "método no virtual en CB\n";
}

class CD1 : public CB
{
  public:
    void mVirtual1();         // método virtual
    virtual void mVirtual2(); // método virtual
    void mNoVirtual();        // método no virtual
};
void CD1::mVirtual1()
{
  cout << "método virtual 1 en CD1\n";
}
void CD1::mVirtual2()
{
  cout << "método virtual 2 en CD1\n";
}
void CD1::mNoVirtual()
{
  cout << "método no virtual en CD1\n";
}

class CD2 : public CD1
{
  public:
    void mVirtual1();  // método virtual
    void mVirtual2();  // método virtual
    void mNoVirtual(); // método no virtual
};
void CD2::mVirtual1()
{
  cout << "método virtual 1 en CD2\n";
}
void CD2::mVirtual2()
{
  cout << "método virtual 2 en CD2\n";
}
void CD2::mNoVirtual()
{
  cout << "método no virtual en CD2\n";
}

void fx(CB *p) // función externa
{
  p->mVirtual1();
  // ...
}

int main()
{
  CB *p1CB = new CD1;   // puntero a CB que apunta a un objeto CD1
  CD1 *p1CD1 = new CD2; // puntero a CD1 que apunta a un objeto CD2
  CB *p2CB = new CD2;   // puntero a CB que apunta a un objeto CD2
  
  // Llamadas a los métodos
  p1CB->mVirtual1();       // llama a CD1::mVirtual1
  p1CB->mNoVirtual();      // llama a CB::mNoVirtual
  p1CB->CB::mVirtual1();   // llama a CB::mVirtual1
  p1CD1->mVirtual2();      // llama a CD2::mVirtual2
  p1CD1->mNoVirtual();     // llama a CD1::mNoVirtual
  p1CD1->CD1::mVirtual2(); // llama a CD1::mVirtual2
  fx(p2CB);                // llama a CD2::mVirtual1
  
  delete p1CB;
  delete p1CD1;
  delete p2CB;
  system("pause");
}
