Как оптимизировать внешнюю ссылку на интерфейс в C ++? - PullRequest
0 голосов
/ 05 февраля 2010

Используя VC8, я создаю два модуля, похожих на следующие:

Заголовок

class IFoo
{
    virtual void Bar() = 0;
};

Модуль A

extern IFoo& Foo;

void DoStuff()
{
    Foo.Bar();
}

Модуль B

IFoo& Foo = ConcreteFoo();

VC8 обрабатывает это, по существу трактуя 'Foo' как указатель на IFoo. Везде, где он видит Foo.Bar () (даже в модуле B), он разыменовывает указатель для получения vtable объекта, ищет адрес Bar () и вызывает его. Это немного раздражает, так как Foo на самом деле относится к конкретному объекту и всегда так будет. Было бы хорошо, если бы вы могли сделать что-то вроде следующего:

Модуль A

extern __concrete IFoo& Foo;

Это сообщит компилятору, что вы обещаете предоставить конкретный объект для поддержки этой ссылки. Затем он может сгенерировать специальную внешнюю ссылку на Foo.Bar () и напрямую вызвать метод без двойной разыменования.

Насколько я могу судить, с Visual C ++ это сделать невозможно, что приводит к двум вопросам:

  1. Есть ли способ заставить компилятор VC генерировать прямой вызов метода?
  2. Существуют ли другие компиляторы C ++, которые могут это сделать?

1 Ответ

3 голосов
/ 05 февраля 2010
  1. Не беспокойтесь об одном крошечном поиске vtable, если только профилирование не указывает на узкое место. (Подсказка: скорее всего, не будет.)
  2. Как компилятор должен знать, каким будет конкретный тип возврата ConcreteFoo()? Если Foo::Bar() является виртуальным, компилятор не может создать статический вызов Foo.Bar(), поскольку тип Foo неизвестен во время компиляции.
  3. Если вы знаете фактический тип Foo, скажем Biz, вы можете отказаться от ссылки:

    Модуль A

    extern Biz Foo;
    

    Модуль B

    Biz Foo = ConcreteFoo();
    

    (при условии, что Biz имеет конструктор копирования.)

...