|
Дублирование интерфейса Давайте посмотрим, можно ли обобщить эту концепцию с помощью еще более умных (назовем их «мудрыми») указателей (smarter pointers). Для начала нам придется на некоторое время покинуть своего старого друга, оператор ->. Одно из ограничений оператора -> заключается в следующем: чтобы использовать указатель, клиент также должен знать все об интерфейсе указываемого объекта. class Foo { // Интерфейсная часть, которую бы вам хотелось спрятать подальше }; Ptr<Foo> pf(new Foo); Хммм. Чтобы клиент мог пользоваться указателем, нам придется рассказать ему все что только можно об указываемом объекте Foo. Не хотелось бы. Ниже показан альтернативный вариант. Терпение - все не так страшно, как кажется на первый взгляд. class Foo { friend class Pfoo; protected: Foo(); public: void DoSomething(); void DoSomethingElse(); }; class PFoo { private: Foo* foo; public: PFoo() : foo(new Foo) {} PFoo(const PFoo& pf) : foo(new Foo(*(pf.foo))) {} ~PFoo() { delete Foo; } PFoo& operator=(const PFoo& pf) { if (this != &pf) { delete foo; foo = new Foo(*(pf.foo)); } return *this; } void DoSomething() { foo->DoSomething(); } void DoSomethingElse() { foo->DoSomethingElse(); } }; Произошло следующее: мы воспользовались удобными средствами копирования/вставки текста вашей среды программирования и продублировали в указателе интерфейс указываемого объекта. Чтобы не лениться и не взваливать всю тяжелую работу по делегированию на оператор ->, мы решительно реализовали все функции класса так, что каждая из них перенаправляет вызов функции-прототипу указываемого объекта. Указатели, воспроизводящие интерфейс указываемого объекта, называются интерфейсными указателями (interface pointers). |
Copyright 2005. Климов Александр. All Right Reserved.