Может ли подкласс встроить чисто виртуальный метод, который не встроен в базу? - PullRequest
1 голос
/ 29 сентября 2011

Насколько я понимаю, компилятор может встроить вызов виртуальной функции, когда он знает во время компиляции, какой будет тип объекта во время выполнения ( C ++ faq ).

Что происходит, однако, когда кто-то реализует чисто виртуальный метод из базового класса? Применяются ли те же правила? Будет ли следующий вызов функции встроенным?

class base
{
public:
    virtual void print() = 0;

    virtual void callPrint()
    {
        print(); // will this be inline?
    }
};

class child : public base
{
public:
    void print() { cout << "hello\n"; }
};

int main()
{
    child c;
    c.callPrint();

    return 0;
}

EDIT:

Я думаю, что мой оригинальный пример кода на самом деле был плохим представлением того, что я хотел спросить. Я обновил код, но вопрос остался прежним.

Ответы [ 3 ]

10 голосов
/ 29 сентября 2011

Компилятору никогда не требуется для встроенного вызова функции.В этом случае разрешено встроить вызов функции, потому что он знает конкретный тип c (поскольку он не перенаправляется через указатель или ссылку, компилятор может видеть, где он был выделен какchild).Как таковой, компилятор знает, какая реализация print() используется, и может решить не выполнять косвенную косвенную передачу vtable, а также выбрать встроенную реализацию функции.

Однако, компилятор также может свободно не встроить его;он может вставить прямой вызов child::print() или косвенный через vtable, если решит это сделать.

Эти оптимизации в целом сводятся к правилу «как будто» - компилятор должен вести себя как если бы выполнял полную косвенную vtable - это означает, что результат должен быть таким же, но компилятор может выбрать другой метод достижения результата, если результат тот же,Это включает в себя встраивание и т. Д.

3 голосов
/ 29 сентября 2011

Ответ, конечно, «зависит», но в принципе нет никаких препятствий для оптимизации. На самом деле, вы даже не делаете здесь ничего полиморфного, так что это действительно просто.

Вопрос был бы более интересным, если бы у вас был такой код:

child c;
base & b = c;
b.print();

Дело в том, что на этом этапе компилятор знает, какой конечной целью будет динамическая диспетчеризация (namly child::print()), поэтому он подходит для оптимизации. (Конечно, есть две отдельные возможности для оптимизации: одна за счет избежания динамической отправки и одна из-за того, что тело функции цели видно в TU.)

1 голос
/ 29 сентября 2011

Есть только пара правил, о которых вам следует знать:

1) Компилятору никогда не требуется встроенный метод - даже с использованием директивы или определения метода в заголовке.

2) Полиморфизм ДОЛЖЕН ВСЕГДА РАБОТАТЬ.Это означает, что компилятор предпочтет вызывать функцию через vftable, а не вставлять ее, когда существует возможность динамических вызовов.

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