Для чего на самом деле виртуальная функция? - PullRequest
0 голосов
/ 19 февраля 2012

Я хочу понять назначение виртуальных функций.

Давайте проанализируем этот код, где функция-член не виртуальная:

ПРИМЕР 1:

struct A
{ 
    void foo1() { cout << "foo 1 from A \n"; }
};

struct B : A
{
    void foo1() { cout << "foo 1 from B \n"; }
};

int main()
{
    A *a = new B;
    a->foo1(); // will print "foo 1 from A \n" because A::foo1 isn't virtual

    B *b = new B;
    b->foo1(); // will print "foo 1 from B \n"
}

Как мы видим вывод a->foo1(); будет "foo 1 from A", но я хочу, чтобы функция B выполняла свою собственную функцию foo1. Поэтому я должен переопределить его и сделать A::foo1 виртуальной функцией.

ПРИМЕР 2:

struct A
{ 
    virtual void foo1() { cout << "foo 1 from A \n"; }
};

struct B :  A
{
    void foo1() { cout << "foo 1 from B \n"; }
};

int main()
{
    A *a = new B;
    a->foo1(); // will print "foo 1 from B \n"

    B *b = new B;
    b->foo1(); // will print "foo 1 from B \n"
}

Теперь A::foo1 был переопределен и a->foo1() печатает "foo 1 from B", как мы этого хотим. Однако давайте рассмотрим случай, когда в классе B есть некоторые функции, отсутствующие в A:

ПРИМЕР 3:

struct A
{ 
    int a;
    void foo1() { cout << "foo 1 from A \n"; }
};

struct B : A
{
    int b;
    void foo1() { cout << "foo 1 from B \n"; }
    void foo2() { cout << "foo 2 from B \n"; }
};

int main()
{
  A *a = new B;
  // a->foo2(); // compiler error, a doesn't see foo2 function
  a->foo1();
  // a->b = 1; // compiler error, a doesn't see member variable b
  a->a = 1;

  // We aren't going to do B *b = new A; here because that's nonsense
  B *b = new B;
  b->foo2(); // ok
  b->foo1(); // ok
  b->b = 1; // ok
  b->a = 1; // ok
}

Как мы видим, теперь B не является точной копией A; он наследует A и расширяет его новыми функциями и переменными. Мы не можем сделать a->foo2() или a->b.

Я думаю, что утверждения типа A *a = new B; гораздо более запутаны при чтении или анализе кода, чем B *b = new B;.

Я знаю, что b - указатель на экземпляр B. Разве вас не смущает вопрос о типе объекта, на который указывает A*?

Итак, мой вопрос: для чего мы можем использовать виртуальные функции?

Я не буду использовать его с производным классом, если у него есть переменные или функции, отсутствующие в базовом классе. Намного понятнее создать новый объект, используя B *b = new B;, а не A *a = new B;.

Когда я создаю экземпляр B, используя B *b = new B;, функции-члены A не обязательно должны быть виртуальными, потому что B автоматически переопределит A::foo1 своим собственным foo1.

Поэтому я думаю, что единственное использование для виртуальных функций - это когда мы хотим изменить функциональность во время выполнения.

Возможно, это может быть полезно в таком случае, когда мы хотим изменить исполняемый класс во время выполнения:

A *a;
B b;
C c;

a = &B;
a->foo1();
a = &C;
a->foo1();

В качестве альтернативы, это может быть полезно при передаче аргумента функции:

void execute(A *a)
{
    a->foo1();
}

Я что-то упускаю по этому поводу?

Ответы [ 2 ]

3 голосов
/ 19 февраля 2012

Виртуальные функции являются основным способом реализации полиморфизма во время выполнения в C ++.Поиск полиморфизма в Google может показать вам, что полезно в этой методике.

0 голосов
/ 23 декабря 2013

Виртуальная функция - это способ, которым C ++ реализует концепцию полиморфизма.

В C ++ простая перегрузка методов используется для полиморфизма времени компиляции, когда компилятор связывает методы во время компиляции.

А в случае виртуальной функции компилятор будет использовать методы во время выполнения по мере необходимости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...