C ++: вызов виртуальной функции производного класса - PullRequest
5 голосов
/ 05 июня 2011

Предположим, у меня есть класс с виртуальной функцией и производный класс, который реализует виртуальную функцию другим способом. Предположим, у меня также есть вектор базового класса, используемый для хранения производных классов. Как мне выполнить виртуальную функцию производного класса в векторе, не зная заранее, что такое производный класс? Минимальный код, который иллюстрирует проблему:

#include <iostream>
#include <vector>

class Foo {
public:
    virtual void do_stuff (void) {
        std::cout << "Foo\n";
    }
};

class Bar: public Foo {
public:
    void do_stuff (void) {
        std::cout << "Bar\n";
    }
};

int main (void) {
    std::vector <Foo> foo_vector;
    Bar bar;

    foo_vector.resize (1);
    foo_vector [0] = bar;

    bar.do_stuff ();            /* prints Bar */
    foo_vector [0].do_stuff (); /* prints Foo; should print Bar */
    return 0;
}

Ответы [ 3 ]

14 голосов
/ 05 июня 2011

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

Если прис другой стороны, у вас есть вектор указателей на базу, затем вы просто вызываете виртуальный метод, и вызывается версия производного класса.

2 голосов
/ 05 июня 2011

Класс, который вы на самом деле вызываете, это не класс Bar, а класс Foo. То, что вы делаете на foo_vector [0] = bar;, является вызовом неявного оператора =, который делает все возможное, чтобы что-то умное произошло. Тем не менее, пространство памяти по-прежнему имеет размер Foo, поэтому оно никогда не может быть Bar.

0 голосов
/ 05 июня 2011

При использовании виртуальных функций вы используете указатели на объекты. Таким образом, точная функция вызывается во время выполнения («Как бы я выполнил виртуальную функцию производного класса в векторе, не зная заранее, что такое производный класс?». Что вы здесь имеете в виду, вероятно, «время выполнения»).

Использование пометки функции как виртуальной заключается в том, что вы просите компилятор отложить или выяснить «ТИП» объекта, вызывающего эту функцию во время выполнения, а не обычным способом «время компиляции». Это достигается с помощью указателей на объекты. Таким образом, чтобы выразить это в простой строке «Использовать указатели на объекты, чтобы использовать виртуальные функции».

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