Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Industrial programming >> Linguagem C

Funções virtuais C++

Funções virtuais C++


Neste tutorial, aprenderemos sobre a função virtual C++ e seu uso com a ajuda de exemplos.

Uma função virtual é uma função membro na classe base que esperamos redefinir em classes derivadas.

Basicamente, uma função virtual é usada na classe base para garantir que a função seja substituída . Isso se aplica especialmente aos casos em que um ponteiro de classe base aponta para um objeto de uma classe derivada.

Por exemplo, considere o código abaixo:

class Base {
   public:
    void print() {
        // code
    }
};

class Derived : public Base {
   public:
    void print() {
        // code
    }
};

Mais tarde, se criarmos um ponteiro de Base digite para apontar para um objeto de Derived class e chame o print() função, ele chama o print() função do Base classe.

Em outras palavras, a função de membro de Base não é substituído.
int main() {
    Derived derived1;
    Base* base1 = &derived1;

    // calls function of Base class
    base1->print();

    return 0;
}

Para evitar isso, declaramos o print() função do Base class como virtual usando o virtual palavra-chave.
class Base {
   public:
    virtual void print() {
        // code
    }
};

As funções virtuais são parte integrante do polimorfismo em C++. Para saber mais, confira nosso tutorial sobre Polimorfismo C++.

Exemplo 1:função virtual C++

#include <iostream>
using namespace std;

class Base {
   public:
    virtual void print() {
        cout << "Base Function" << endl;
    }
};

class Derived : public Base {
   public:
    void print() {
        cout << "Derived Function" << endl;
    }
};

int main() {
    Derived derived1;

    // pointer of Base type that points to derived1
    Base* base1 = &derived1;

    // calls member function of Derived class
    base1->print();

    return 0;
}

Saída
Derived Function



Aqui, declaramos o print() função de Base como virtual .

Portanto, esta função é substituída mesmo quando usamos um ponteiro de Base tipo que aponta para o Derived objeto derivado1 .

Identificador de substituição de C++


O C++ 11 nos deu um novo identificador override que é muito útil para evitar bugs ao usar funções virtuais.

Esse identificador especifica as funções de membro das classes derivadas que substituem a função de membro da classe base.

Por exemplo,
class Base {
   public:
    virtual void print() {
        // code
    }
};

class Derived : public Base {
   public:
    void print() override {
        // code
    }
};

Se usarmos um protótipo de função em Derived class e definir essa função fora da classe, então usamos o seguinte código:
class Derived : public Base {
   public:
    // function prototype
    void print() override;
};

// function definition
void Derived::print() {
    // code
}

Uso de substituição C++


Ao usar funções virtuais, é possível cometer erros ao declarar as funções-membro das classes derivadas.

Usando o override identificador solicita ao compilador para exibir mensagens de erro quando esses erros são cometidos.

Caso contrário, o programa simplesmente compilará, mas a função virtual não será substituída.

Alguns desses possíveis erros são:
  • Funções com nomes incorretos: Por exemplo, se a função virtual na classe base for denominada print() , mas acidentalmente nomeamos a função de substituição na classe derivada como pint() .
  • Funções com diferentes tipos de retorno: Se a função virtual for, digamos, de void tipo, mas a função na classe derivada é de int tipo.
  • Funções com parâmetros diferentes: Se os parâmetros da função virtual e as funções nas classes derivadas não corresponderem.
  • Nenhuma função virtual é declarada na classe base.

Uso de funções virtuais C++


Suponha que tenhamos uma classe base Animal e classes derivadas Dog e Cat .

Suponha que cada classe tenha um membro de dados chamado type . Suponha que essas variáveis ​​sejam inicializadas por meio de seus respectivos construtores.
class Animal {
   private:
    string type;
    ... .. ...
    public:
      Animal(): type("Animal") {}
    ... .. ...
};

class Dog : public Animal {
   private:
    string type;
    ... .. ...
    public:
      Animal(): type("Dog") {}
    ... .. ...
};

class Cat : public Animal {
   private:
    string type;
      ... .. ...
    public:
      Animal(): type("Cat") {}
    ... .. ...
};

Agora, vamos supor que nosso programa exija que criemos dois public funções para cada classe:
  1. getType() para retornar o valor de tipo
  2. print() para imprimir o valor de tipo

Poderíamos criar essas duas funções em cada classe separadamente e substituí-las, o que será longo e tedioso.

Ou podemos fazer getType() virtuais no Animal class e, em seguida, crie um print() único e separado função que aceita um ponteiro de Animal tipo como seu argumento. Podemos então usar essa única função para substituir a função virtual.
class Animal {
    ... .. ...
   public:
    ... .. ...
    virtual string getType {...}
};

... .. ...
... .. ...

void print(Animal* ani) {
    cout << "Animal: " << ani->getType() << endl;
}

Isso tornará o código mais curto , limpeza , e menos repetitivo .

Exemplo 2:Demonstração de função virtual C++

// C++ program to demonstrate the use of virtual function

#include <iostream>
#include <string>
using namespace std;

class Animal {
   private:
    string type;

   public:
    // constructor to initialize type
    Animal() : type("Animal") {}

    // declare virtual function
    virtual string getType() {
        return type;
    }
};

class Dog : public Animal {
   private:
    string type;

   public:
    // constructor to initialize type
    Dog() : type("Dog") {}

    string getType() override {
        return type;
    }
};

class Cat : public Animal {
   private:
    string type;

   public:
    // constructor to initialize type
    Cat() : type("Cat") {}

    string getType() override {
        return type;
    }
};

void print(Animal* ani) {
    cout << "Animal: " << ani->getType() << endl;
}

int main() {
    Animal* animal1 = new Animal();
    Animal* dog1 = new Dog();
    Animal* cat1 = new Cat();

    print(animal1);
    print(dog1);
    print(cat1);

    return 0;
}

Saída
Animal: Animal
Animal: Dog
Animal: Cat

Aqui, usamos a função virtual getType() e um Animal ponteiro ani para evitar repetir o print() função em cada classe.
void print(Animal* ani) {
    cout << "Animal: " << ani->getType() << endl;
}

Em main() , criamos 3 Animal ponteiros para criar dinamicamente objetos de Animal , Dog e Cat Aulas.
// dynamically create objects using Animal pointers
Animal* animal1 = new Animal();
Animal* dog1 = new Dog();
Animal* cat1 = new Cat();

Em seguida, chamamos o print() função usando estes ponteiros:
  1. Quando print(animal1) é chamado, o ponteiro aponta para um Animal objeto. Então, a função virtual em Animal classe é executada dentro de print() .
  2. Quando print(dog1) é chamado, o ponteiro aponta para um Dog objeto. Assim, a função virtual é substituída e a função de Dog é executado dentro de print() .
  3. Quando print(cat1) é chamado, o ponteiro aponta para um Cat objeto. Assim, a função virtual é substituída e a função de Cat é executado dentro de print() .

Linguagem C

  1. Passando array para uma função na programação C++
  2. Classes e objetos C++
  3. Função de amigo C++ e classes de amigo
  4. Modelos de classe C++
  5. Funções C++ com exemplos de programas
  6. Funções Verilog
  7. C - Funções
  8. Classes de armazenamento em C++
  9. Sobrecarga de C++ (operador e função)
  10. Polimorfismo em C++