Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Программирование с использованием gtkmm 3. Умный указатель RefPtr

Оригинал: Programming with gtkmm 3
Авторы: Murray Cumming, Bernhard Rieder, Jonathon Jongsma, Ole Laursen, Marko Anastasov, Daniel Elstner, Chris Vine, David King, Pedro Ferreira, Kjell Ahlstedt
Дата публикации: 15 Октября 2013 г.
Перевод: А.Панин
Дата перевода: 25 Апреля 2014 г.

Приложение A. Умный указатель RefPtr

Умный указатель для работы с объектами gtkmm реализован в рамках класса Glib::RefPtr. Если говорить точнее, этот указатель является умным указателем с подсчетом ссылок. Вы должны быть знакомы с такими классами, как std::auto_ptr<>, std::unique_ptr<> и std::shared_ptr<>, которые также реализуют умные указатели. Класс Glib::RefPtr<> похож на класс std::shared_ptr<>, в рамках которого также осуществляется подсчет ссылок. Класс Glib::RefPtr<> был представлен задолго до появления в стандартной библиотеке языка программирования C++ класса умного указателя с подсчетом ссылок.

Справочная информация

Умный указатель ведет себя практически так же, как и обычный указатель. Ниже приведено несколько примеров его использования.

A.1. Копирование

Вы можете копировать умные указатели практически так же, как и обычные указатели. Но, в отличие от обычных указателей, вам не придется беспокоиться об уничтожении расположенного уровнем ниже экземпляра класса.
Glib::RefPtr<Gdk::Pixbuf> refPixbuf = Gdk::Pixbuf::create_from_file(filename);
Glib::RefPtr<Gdk::Pixbuf> refPixbuf2 = refPixbuf;
Конечно же, это означает, что вы можете хранить умные указатели в таких стандартных контейнерах, как std::vector и std::list.
std::list< Glib::RefPtr<Gdk::Pixbuf> > listPixbufs;
Glib::RefPtr<Gdk::Pixbuf> refPixbuf = Gdk::Pixbuf::create_from_file(filename);
listPixbufs.push_back(refPixbuf);

A.2. Разыменование

Вы можете разыменовывать умный указатель с помощью оператора -> для вызова методов расположенного уровнем ниже экземпляра класса точно так же, как это делается при работе с обычным указателем.
Glib::RefPtr<Gdk::Pixbuf> refPixbuf = Gdk::Pixbuf::create_from_file(filename);
int width = refPixbuf->get_width();
Но, в отличие от большинства умных указателей, вы не можете использовать оператор * для доступа к расположенному уровнем ниже экземпляру класса.
Glib::RefPtr<Gdk::Pixbuf> refPixbuf = Gdk::Pixbuf::create_from_file(filename);
Gdk::Pixbuf& underlying = *refPixbuf; //Ошибка синтаксиса - компиляция будет прервана.

A.3. Преобразование

Вы можете осуществлять преобразование умных указателей к базовым типам точно так же, как это делается при работе с обычными указателями.
Glib::RefPtr<Gtk::TreeStore> refStore = Gtk::TreeStore::create(columns);
Glib::RefPtr<Gtk::TreeModel> refModel = refStore;

Это означает, что любой метод, принимающий аргумент базового типа const Glib::RefPtr<BaseType> также может принимать аргумент унаследованного от базового типа const Glib::RefPtr<DerivedType>. В данном случае будет осуществлено точно такое же неявное преобразование типов, как и при работе с обычным указателем.

Также вы можете осуществить преобразование указателя к унаследованному от базового типу, но синтаксис этого преобразования будет немного отличаться от синтаксиса такого же преобразования в случае работы с обычным указателем.
Glib::RefPtr<Gtk::TreeStore> refStore =
Glib::RefPtr<Gtk::TreeStore>::cast_dynamic(refModel);
Glib::RefPtr<Gtk::TreeStore> refStore2 =
Glib::RefPtr<Gtk::TreeStore>::cast_static(refModel);

A.4. Проверка на нулевое значение

Как и при работе с обычными указателями, вы можете проверить, указывает ли умный указатель на что-либо.
Glib::RefPtr<Gtk::TreeModel> refModel = m_TreeView.get_model();
if(refModel)
{
  int cols_count = refModel->get_n_columns();
  ...
}

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

A.5. Постоянство значений

Методика использования ключевого слова const в языке программирования C++ не достаточно очевидна. Вы можете не осознавать того, что объявление const Something* позволяет описать указатель на неизменный объект const Something. При этом может изменяться указатель, но не объект Something, на который он указывает.

Исходя из этого, в случае работы с умным указателем эквивалентом записи Something* для параметра метода является запись const Glib::RefPtr<Something>&, а эквивалентом записи const Something* является запись const Glib::RefPtr<const Something>&.

Запись const ... & используется в обоих случаях для повышения производительности операции аналогично тому, как для передачи строки в качестве параметра метода с целью исключения излишних операций копирования используется запись std::string& вместо записи std::string.


Следующий раздел : Приложение B. Сигналы.