2013-05-15 6 views
3

Недавно я решил использовать инертный виртуальный интерфейс (NVI) для разработки интерфейса на C++, в основном с целью использования параметра со значением по умолчанию (таким образом, избегая проблем, вызванных тем, что параметры по умолчанию статически связаны) ,Использование идиомы не-виртуального интерфейса, может/будет ли моя не виртуальная функция быть встроенной?

я пришел с довольно тривиальной декларацией для моего класса, глядя, как это:

class Interface{ 

public: 
    void func(Parameter p = 0); 
    virtual ~Interface(); 
private: 
    virtual void doFunc(Parameter p)=0; 

}; 

void Interface::func(Parameter p){ doFunc(p); } 
Interface::~Interface() {} 

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

Тогда в этом случае будет помечен кандидат для встраивания? func()? Это не виртуальная функция, но все же звонки виртуальная функция. Это делает его встроенным?

Дополнительный вопрос: стоит ли это? Тело состоит только из одного заявления.

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

Спасибо!

+0

, который полностью зависит от вашего компилятора, его текущей версии, функций сборки, параметров для нее, платформы, инструментов построения и т. Д. – PlasmaHH

+1

Возможно, я ошибаюсь, но я считаю, что компилятору разрешено встроить даже «виртуальные» функции в случаях где он может точно знать, какую функцию вызывать. – ereOn

+0

@ereOn Я был бы очень удивлен этим, поскольку вложение означает «Заменить вызов функций своим телом во время компиляции» и виртуальными средствами «Подождите, пока время выполнения не будет определено, какую функцию нужно вызывать». – JBL

ответ

2

Я знаю, что предоставление тела функции в заголовке автоматически маркировать функцию в качестве кандидата на встраивание

больше или меньше; но вы это делаете, предоставляя тело функции в определении класса или явно объявляя его inline, если оно находится в заголовке. В противном случае функция подчиняется Правилу Единого определения, и вы получите ошибки, если вы включите заголовок в несколько единиц перевода.

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

Тогда, в этом случае, будет ли функция func() отмечена кандидатом для встраивания? Это не виртуальная функция, но по-прежнему вызывает виртуальную функцию. Это делает его встроенным?

Да, все функции являются кандидатами на inlining. Если они назовут себя, то, очевидно, вы не можете включить все звонки; а также если функция не известна во время компиляции (например, потому, что ее нужно вызвать практически или через указатель функции). В этом случае вложение функции заменит прямой вызов на func() с виртуальным вызовом doFunc().

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

struct MyImplementation : Interface {/*whatever*/}; 
MyImplementation thing; 
thing.func(); // Known to be MyImplementation, func and doFunc can be inlined 

Дополнительный вопрос: это было бы стоит?

Это зависит от того, что это такое. Если вы имеете в виду время компиляции, то пока функция остается коротким, вы можете получить некоторую выгоду (возможно, значительную, если функция вызывается много раз) для незначительной стоимости. Если вы имеете в виду стоимость траты времени, выбирая, куда ее поместить, то, вероятно, нет; просто положите его куда удобнее.

+0

Спасибо за ваш хорошо объясненный ответ! – JBL