Al leer un libro de texto, he tenido la impresión de que anular funciones virtuales solo funciona cuando se usa un puntero o una referencia al objeto. El libro demuestra la creación de un puntero del tipo de clase base que apunta a un objeto del tipo de clase derivado, y lo utiliza para demostrar una anulación de función virtual.

Sin embargo, ahora me he encontrado con lo siguiente. No hay un puntero a la vista, y esperaba que hacer que la función1 sea virtual no haría la diferencia, pero lo hace. Claramente me falta algo aquí y agradecería una explicación de lo que es. Lo siento si mi explicación no es clara; También espero que esto se haya preguntado antes, pero no se me ocurrió qué buscar.

using namespace std;

class ClassA
{
public:
    void function1(); // virtual or not?
    void function2();
};

class ClassB : public ClassA
{
public:
    void function1();
};

int main()
{
    ClassA objA;
    ClassB objB;

    objA.function1();
    cout << "\n";
    objA.function2();
    cout << "\n";
    objB.function1();
    cout << "\n";
    objB.function2(); // Fourth call
    cout << "\n";
}

void ClassA::function1() { cout << "ClassA::function1\n"; }

void ClassA::function2()
{
    cout << "ClassA::function2\n";
    function1(); // For the fourth call ClassA::function1()
                    // is called if ClassA::function1() is not virtual
                    // but ClassB:function1() is called if it is.  Why? 
}

void ClassB::function1() { cout << "ClassB::function1\n"; }

Muchas gracias por cualquier ayuda.

0
Hippo 13 ene. 2018 a las 21:29

3 respuestas

La mejor respuesta

Ejemplo de virtual sin punteros explícitos:

class A
{
    public:
        virtual void f1()
        {
            cout << "A::f1()" << endl;
        }

        void f2()
        {
            f1();
        }
};

class B : public A
{
    public:
        void f1() override
        {
            cout << "B::f1()" << endl;
        }
};

int main()
{
    A a;
    B b;
    a.f2();
    b.f2();
}
0
Sid S 13 ene. 2018 a las 18:45

La función1 no es virtual, obj2 llama a la clase1 función1 porque es un objeto clasB, el compilador primero busca el tipo más derivado para una función, luego la base más a la izquierda (y luego a través de las bases de esa base), y luego la siguiente base en múltiples situaciones de herencia. Si tomó una clase A * para obj2 y llamó a la función1, llamaría a la clase1 función1.

0
SoronelHaetir 13 ene. 2018 a las 18:45

No es una función virtual ya que no está marcada como una. Es simplemente una función pública accesible desde una clase / objeto derivado. Su código tampoco exhibe un comportamiento polimórfico. Dicho esto, ninguna de sus funciones es virtual ni anulación. Un ejemplo trivial para la instalación polimórfica sería:

#include <iostream>
#include <memory>

class ClassA {
public:
    virtual void function1() { // now virtual
        std::cout << "ClassA::function1\n";
    }
};

class ClassB : public ClassA {
public:
    void function1() override {
        std::cout << "ClassB::function1\n";
    }
};

int main() {
    std::unique_ptr<ClassA> p = std::make_unique<ClassB>();
    p->function1(); // now calls class B function, overrides class A behavior
}

O a través de referencias:

int main() {
    ClassB objB;
    ClassA& ro = objB;
    ro.function1(); // now calls class B function, overrides class A behavior
}

Hay pocos beneficios en las funciones de marcado como virtual y override si no está utilizando el comportamiento polimórfico.

1
Ron 13 ene. 2018 a las 23:46