2013-02-22 8 views
1

Если посмотреть на <streambuf> заголовочный файл в VS2010 вы увидите определение этой функции-члена, какПочему basic_streambuf :: pubseekoff() не является чистой виртуальной функцией?

pos_type pubseekoff(off_type _Off, ios_base::seekdir _Way, 
       ios_base::openmode _Mode = ios_base::in | ios_base::out) 
{ // change position by _Off, according to _Way, _Mode 
    return (seekoff(_Off, _Way, _Mode)); 
} 

где seekoff является виртуальной функцией, которая переопределяется в производных классов basic_filebuf и basic_stringbuf и который ничего не делает в базовом классе basic_streambuf, как можно увидеть ниже:

virtual pos_type seekoff(off_type, ios_base::seekdir, 
         ios_base::openmode = ios_base::in | ios_base::out) 
{ // change position by offset, according to way and mode 
    return (streampos(_BADOFF)); 
} 

Я не смог найти определение _BADOFF, но это, вероятно, -1. Но это действительно не имеет значения. Эта функция, а не pubseekoff, никогда не будет вызываться, так как класс basic_streambuf является абстрактным классом (его конструкторы защищены).

Обратите внимание, что компилятор gcc использует ту же технику. Почему двум компиляторам пришлось прибегнуть к функциям-членам seekoff() вместо простого объявления pubseekoff как чистого виртуального в basic_streambuf и определения его в каждом из производных классов basic_filebuf и basic_stringbuf?

+0

возможно, потому что стандарт предусматривает его? – PlasmaHH

ответ

3

По той же причине вы обычно не делаете виртуальные функции общедоступными. Публичные функции определяют интерфейс, а базовый класс должен уметь их захватывать, если он хочет обеспечить соответствие этого интерфейса . Существуют исключения, когда задействована инверсия управления , но в большинстве случаев вы просто не открываете виртуальные функции . Как бы вы ввели предварительные и послесловия чеки, если вы это сделали? (См., Например, http://www.gotw.ca/publications/mill18.htm.)

+0

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

+0

@ user1577873 Базовый класс определяет контракт для каждой функции, включая такие вещи, как pre- и post-conditions. Чтобы обеспечить соблюдение предварительных и пост-условий, базовый класс должен иметь возможность вставлять код до и после вызова виртуальной функции. Он должен иметь возможность «захватить» вызов, а не передавать вызов непосредственно производному классу. –

+0

+1 Я думаю, что у меня все есть. Отличный ответ. Tks –