Considere el siguiente código C ++:

#include <iostream>

using std::cout;

class A
{
public:
    int a;

    A():a(0)
    {
        cout << "A constructor\n";
    }

    virtual void f()
    {
        cout << "f inside A\n";
    }
};

class C : public A
{
public:
    int c;

    virtual void f()
    {
        cout << "f inside C\n";
    }

    C():c(0)
    {
        cout << "C constructor\n";
    }
};

int main()
{
    A varA = C();

    cout << "Size of C class: " << sizeof(C) << "\n";
    cout << "Size of varA object: " << sizeof(varA) << "\n";

    C* varC = static_cast<C*>(&varA);
    varC->f();

    cout << "varC->a is " << varC->a << "\n";
    cout << "varC->c is " << varC->c << "\n";
}

La salida de este programa es:

A constructor
C constructor
Size of C class: 16
Size of varA object: 8
f inside A
varC->a is 0
varC->c is 1726166356

Inicializo el objeto varA con el constructor de la clase C. Se llaman a los constructores de las clases A y C, pero el varA es simplemente un objeto A. Transmito la dirección de varA al tipo C* e intento llamar a su función f(), pero imprime la función f() de la clase A, así que deducir que se usa el mecanismo de enlace temprano para llamarlo. Creo que si llamo al constructor de la clase derivada, como en este caso, obtengo el mismo objeto si hubiera llamado al constructor base. Creo que la única diferencia es que se llaman los otros constructores. ¿Es correcta mi suposición o hay otras diferencias?

0
Radioga 14 dic. 2016 a las 17:49

2 respuestas

La mejor respuesta

Ejemplo clásico de rebanar. A varA = C(); te deja con un objeto de tipo estático y dinámico de A. Como resultado, C* varC = static_cast<C*>(&varA); exhibe un comportamiento indefinido.

4
SergeyA 14 dic. 2016 a las 14:51

Sin embargo, puede almacenar una clase derivada completa en un puntero de clase base:

int main() {        
  A* varA = new C();
  C* varC = static_cast<C*>(varA);
  varC->f();

  cout << "varC->a is " << varC->a << endl;
  cout << "varC->b is " << varC->b << endl;
  cout << "varC->c is " << varC->c << endl;
} // oops, forgot to delete varA/varC, memory leak!
1
Jack Deeth 14 dic. 2016 a las 15:29