2014-09-01 6 views
1

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

Предположим, мы имеем:

class Base{ 
public: 
    void foo(){ bar(); } 
private: 
    virtual void bar() =0 {/*something*/} 
}; 

Производный класс Base должен определить бар (или иметь его чисто виртуальный, но забывать об этом ни на минуту). Поскольку Base :: bar является закрытым, он не может использоваться производным классом. Поскольку база абстрактна, я не могу создать базовый объект, поэтому я могу вызывать foo только на производных классах, но это означает, что Base :: bar никогда не будет вызван! Конечно, я мог бы определить Foo:

void Base::foo(){ 
    bar(); 
    Base::bar(); 
} 

Но для чего? Не было бы лучше определить не виртуальную частную функцию с телом бара (и заменить Base :: bar на него), и сделать тело чистого виртуального пустым?

Если да, то почему у меня должен быть бар частный (и не защищен)?

PS: Я попытался найти решение в Интернете, и я знаю, что есть сообщения, такие как ->C++: Private virtual functions vs. pure virtual functions, но они помогают в понимании частной виртуальной функции, а не частной виртуальной функции PURE. Если я ошибаюсь, простите меня!

+0

'virtual void bar() = 0 {/ * something * /}'? – ChiefTwoPencils

+1

Вам не нужно предоставлять определение для чистых виртуальных функций, если это то, о чем вы просите. –

+0

@ T.C. Я думаю, вы удалили комментарий, на который я отвечал. –

ответ

1

Так что в целом картина является реализовать публичную не виртуальную функцию и частную или защищенную виртуальную функцию, похоже, что вы уже исследовали это, но это обычно известно как Template Method Pattern, с дополнительными пояснениями Herb Sutter here и here.

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

Есть некоторые угловые случаи, в которых вы хотите обеспечить реализацию для чистой виртуальной функции, Herb Sutter again, перечисляет два, один для обеспечения поведения по умолчанию, но принудительно производные классы вызываются, а другой - для защиты от компилятора которые могут получить чистую виртуальную функцию.

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

+0

«Есть некоторые угловые случаи, в которых вы захотите предоставить реализацию для чистой виртуальной функции, Herb Sutter снова, перечисляет два, один для обеспечения поведения по умолчанию, но принудительно производные классы, чтобы уловно назвать«, эта причина может быть действительной, если i имеют эту чистую виртуальную функцию, защищенную (или общедоступную), но не закрытую. Но, во-вторых, может быть разумным: на всякий случай, если произойдет некоторая ошибка, я узнаю и сделаю ее конфиденциальной, я не позволю производным классам использовать эту функцию «предупреждения»; .. – Toccio

+0

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

+0

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

0

bar() все еще может быть вызван другими членами класса Base, конечно.

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

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

Смежные вопросы