|
Программирование >> Обобщенные обратные вызовы
return CalcО.Test(); Здесь мы также не можем пройти второй шаг: разрешение перегрузки не сможет найти ни одной соответствующей функции в списке кандидатов (в котором теперь находится единственная функция Calc:; Twice (string)), поскольку аргумент типа int не может быть преобразован в stri ng. Компилятор просто не доберется до проверки доступности. Запомните, как только найдена область действия, в которой имеется хотя бы один объект с заданным именем, поиск завершается, даже если канди-дат(ы) оказываются не соответствующими типам аргументов и не могут быть вызваны и/или оказываются недоступны. Поиск других кандидатов в охватывающей области действия проводиться не будет*. Итак, мы получили еше одну часть ответа на вопрос о закрытых членах. Закрытый член видим всему коду, которому видно определение класса. Это означает, что он участвует в поиске имен и разрешении перегрузки и, таким образом, может сделать вызов некорректным или неоднозначным несмотря на то, что сам он, в любом случае, не может быть вызван. Бьярн Страуструп так писал об этом в своей книге [Stroustrup94]: Если бы спецификации public/private в первую очередь управляли не доступностью, а видимостью, изменение доступности члена с public на private могло бы привести к незаметному изменению смысла программы - от одной корректной интерпретации [в нашем примере вызов Calc:: Twice (int)] к другой [в нашем примере вызов Calc: : Twice (double)]. Это не решающий аргумент, но принятое решение позволяет программистам в процессе отладки добавлять и удалять спецификаторы public и private, не опасаясь, что программа незаметно изменит свой смысл. Я до сих пор гадаю, не явилось ли это решение неким озарением . И снова доступность Я уже говорил о том, что закрытое имя члена доступно (может использоваться) только для других членов и друзей. Обратите внимание, что я преднамеренно не сказал может быть вызван только другими членами или друзьями , поскольку на самом деле это не так. Доступность определяет, вправе ли код использовать имя. Позвольте мне подчеркнуть .это цитатой из стандарта. Член класса может быть закрытым (private), т.е. его имя может использоваться только членами и друзьями класса, в котором он объявлен. Если код, который имеет право непосредственного использования имени (в данном случае член класса или друг) использует эго имя для создания указателя на функцию, а затем передает его другому коду, то получивший его код может воспользоваться этим указателем независимо от того, имеет ли он право на использование имени - имя ему больше не нужно, так как у него есть указатель. Пример 16-5 иллюстрирует применение этого способа на практике - функция-член, имеющая доступ к имени Twice (int), использует этот доступ для передачи указателя на данный член. пример 16-5: передача доступа class Calc; typedef int (calc::*РметЬег)(int) ; с I ass Calc { public: PMember coughltup() { return &Calc::Twice; } Поиск прекращается даже в тех случаях, когда найденное во время поиска имя не является именем функции. - Прим. ред. private: int TwiceC int i ); int main() { Calс с; PMember p = c.CoughltUp(); дает доступ к Twice(int) return (c.*p)( 21 ); ok Cm. также [Newkirk97], где описывается полезное применение преднамеренной утечки деталей закрытой реализации, Итак, мы получили еще одну часть ответа на вопрос о закрытых членах. Код, который имеет доступ к члену, может передать этот доступ любому другому коду, передав ему указатель на этот член. И наконец, имеется еще один способ, которым некоторые классы могут переносимо и в полном соответствии со стагщартом дать всем права доступа к закрытому члену: эго щаблоны членов. В задаче 15 мы рассмотрели несколько способов получения доступа к закрытым частям класса. Большинство из них не законны , но один из них стопроцентно соответствует стандарту. пример 16-6: адаптированный пример 15-4 В заголовочном файле class X { public: tempiate<class T> void f( const T& t ) { ... ... private: int private..; В пользовательском коде namespace { struct Y {}; templateo void x::f( const Y& ) { private =2; Злобный смех Что здесь произошло? Любой шаблон члена может быть специализирован для любого типа. Специализируя его для какого-то своего уникального типа (уникальность обеспечивается безымянным пространством имен), вы создаете собственную функцию-член, а член класса имеет доступ ко всем частям класса. Итак, вот последняя часть ответа на вопрос о закрытых членах: Имя закрытого члена доступно только другим членам (включая явные инстанцирования шаблонов членов) и друзьям. Резюме Итак, насколько же закрыты закрытые члены? Вот что мы выяснили. Имя закрытого члена доступно только другим членам (включая явные инстанцирования шаблонов членов) и друзьям. Но код, который имеет доступ к члену, может передать эти права доступа любому другому коду посредством указателя на данный член. Закрытый член видим любому коду, которому видно определение класса. Это означает, что типы его параметров должны быть объявлены, даже если они не используются в единице трансляции, и что он может сделать вызов некорректным или неоднозначным, несмотря на то, что сам вызван быть не может.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |