|
|
Страничка Ильи Жаркова | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Статья
|
|||||||||||||||||||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||||||||||||||||||
![]()
|
Некоторые аспекты использования “свойств” в языке программирования C++ И.А. Жарков [email protected] Эта статья написана в результате длительных дискуссий в Интернет-форумах на тему "Свойства в С++". Она будет полезна всем программистам, активно использующим свойства, и не только программирующим на языке С++, всем тем, кто раздумывает, использовать или не использовать их, а также начинающим программистам. ООП базируется на трех основных принципах: инкапсуляция, наследование и полиморфизм. Рассмотрим последний принцип - инкапсуляцию. По определению, инкапсуляция - это процесс отделения друг от друга элементов объекта, определяющих его устройство и поведение. Другими словами, отделение интерфейса от реализации. В C++ единицей инкапсуляции является класс. Каждый класс, для любого постороннего класса, выступает "черным ящиком". Доступ к его возможностям мы получаем через интерфейс, т.е. через открытые методы. Каждое из "свойств" является именно таким объектом. То есть только они знают, что произойдет при том или ином воздействии на объект. Известные способы реализации этих объектов в таких языках программирования, как C#, Delphi, нарушают этот принцип, поскольку в них реализация поведения "свойства" возлагается на объект, которому он принадлежит. Ниже приводится сравнение реализации “свойств” сначала с помощью расширения языка С++, введенное в компилятор VC++ ради поддержки такого стиля программирования в COM, а затем в С# - новом языке программирования от компании Microsoft. class Object1 { // VC++ но не С++ т.к. __declspec() не входит в стандарт С++private: int m_value; public: __declspec(property(get=get_Value, put=set_Value)) int Value; int get_Value() { return m_value; }
void set_Value(int value) { m_value = value;
}
}; public class Object2 { // C# - свойства входят в стандарт private int m_value; // закрытая переменная public int Value { // свойство, используемое для доступа к закрытой переменной get { return m_value; } set { m_value = value; } } }
Необходимо ли включить свойства в стандарт языка C++ или без них можно обойтись? Есть несколько правил добавления новых расширений языка. Главные из них такие: как повлияет изменение на эффективность исполняемого кода? Какие стили программирования и проектирования поддерживает данное изменение, и каким стилям оно мешает? Существуют ли альтернативные способы решения этой проблемы? Коротко рассмотрим эти вопросы. 1. Как повлияет изменение на эффективность исполняемого кода? Все арифметические операции над свойством Value раскрываются в вызовы функций set_Value и get_Value. То есть Value= Value+1; превращается в set_Value(get_Value()+1); то же самое будет выполнено и для Value+=1; и для Value++; Это означает, что мы уже не можем самостоятельно влиять на результирующий код – приходиться полагаться на “разумность” компилятора, “вдруг” ему удастся создать более качественный код. 2. Какие стили программирования и проектирования поддерживает данное изменение, и каким стилям оно мешает? Нельзя сказать, что с помощью свойств вводится новый стиль программирования, скорее они делают более расплывчатым понятия данные, сокрытие данных и осложняют проектирование иерархии классов (нельзя забывать о нарушении принципов ООП, о которых говорилось выше). И, наконец, последний вопрос. 3. Существуют ли альтернативные способы решения этой проблемы? Безусловно существуют. Причем вполне стандартным, а значит, уже проверенным способом. class Property {private: int m_value; public: Property & operator=(int val) { // операторприсваивания объекту значение val m_value=val; return *this; } operator int() const { // оператор преобразования объекта в тип int return m_value; } }; Это, как можно заметить, реализация самого свойства. Некоторый объект Object3 сможет его использовать, например, так: class Object3 {private: // … public: // … Property Value;
// … }; Из выше сказанного можно заключить, что прямая поддержка свойств в языке программирования C++ не требуется. Единственно разумный случай, когда может потребоваться свойства, наподобие __declspec(property()) в VC++, и который может оправдать нарушение принципов ООП (если это вообще можно оправдать!), такой: имеется законченный, большой класс, в котором есть два метода, назовем их Get() и Set(). И вот понадобилось, с минимальными изменениями класса, упростить их использование. Создаем переменную при "записи", в которую вызывается Set(), а при "извлечении" из нее значения - Get(). Какой способ использовать для реализации "свойства", зависит от программиста, от того, как он станет проектировать свою программу. Вот цитата Б.Страуструпа: "Хорошие программы - это продукт хорошего образования, удачного проектирования, адекватного тестирования и т.д., а не наличия в языке средств, которые предположительно должны использоваться только "правильно". Употребить во вред можно любое средство". Литература. 1. Страуструп Б. Язык программирования C++. М.: “Невский Диалект” - “Издательство БИНОМ”, 1999. 2. Страуструп Б. Дизайн и эволюция языка C++. М.: ДМК Пресс, 2000. |
|||
![]()
| Хостинг любезно предоставлен ISP "Венс" |
|
Страница была обновленна: 07.11.2002 |
|
Все замечания по содержанию сайта отправляйте по адресу [email protected] |