Глава 15.4 Поддержка информации времени выполнения (Run-Time Type Information)

March 21st, 2010 Begemot Posted in Oбщее

Как то эта глава далась мне особенно тяжко и во время перевода и во время вычитки, два раза я возвращался  к редактированию и все равно по моему все очень криво:( Единственное что глава вроде не сильно важная и не очень большая, так что думаю это не смертельно.

Поддержка информации времени выполнения (Run-Time Type Information)

Как и большинство других фреймворков, wxWidgets обеспечивает более качественную работу с RTTI (информацией времени выполнения о типе), по сравнению со стандартным механизмом RTTI языка C++. Это может быть полезно для принятия решений, основанных на типе объекта во время выполнения программы или для сообщений об ошибках, как мы могли увидеть в предыдущей главе. Так же это дает возможность динамически создавать объекты, просто передавая имя класса в виде строки. Необходимым условием поддержки RTTI в классе, является его наследование от wxObject.

Если вам не нужна возможность динамического создания объектов, используйте макрос DECLARE_CLASS(класс) в объявлении класса и IMPLEMENT_CLASS(класс, базовый класс) в файле реализации. Если вы допускаете динамическое создание экземпляров класса с использованием RTTI, используйте DECLARE_DYNAMIC_CLASS(класс) в определении и IMPLEMENT_DYNAMIC_ CLASS(класс, базовый класс) в файле реализации. В последнем случае вы также должны убедиться, что класс имеет конструктор по умолчанию, в противном случае компилятор выдаст предупреждение, при попытке скомпилировать функции, автоматически генерируемые wxWidgets для динамического создания объекта класса.

Пример использования RTTI для динамического создания объекта класса.

class MyRecord: public wxObject
{
DECLARE_DYNAMIC_CLASS(MyRecord)
public:
    MyRecord() {}
    MyRecord(const wxString& name) { m_name = name; }

    void SetName(const wxString& name) { m_name = name; }
    const wxString& GetName() const { return m_name; }
private:
    wxString m_name;
};

IMPLEMENT_DYNAMIC_CLASS(MyRecord, wxObject)

MyRecord* CreateMyRecord(const wxString& name)
{
    MyRecord* rec = wxDynamicCast(wxCreateDynamicObject(wxT("MyRecord")), MyRecord);
    if (rec)
        rec->SetName(name);
    return rec;
}

Когда в коде вызывается функция CreateMyRecord, wxCreateDynamicObject создает требуемый объект, после чего wxDynamicCast или подтверждает, что действительно был создан объект типа MyRecordit или возвращает NULL, в противном случае. Несмотря на то что, это может показаться бесполезным на первый взгляд, динамическое создание объектов весьма удобно при реализации загрузки сложных файлов, содержащих объекты разных типов. Данные могут хранится вместе с именем класса объекта. При чтении файла мы сначала создаем нужный объект, после чего он уже сам может прочесть свои данные.

Есть еще ряд доступных вам RTTI макросов.

CLASSINFO(class) возвращает указатель на связанный с классом объект типа wxClassInfo. Вы можете использовать это вместе wxObject::IsKindOf для проверки типа класса:

if (obj->IsKindOf(CLASSINFO(MyRecord)))
{
    …
}

Используйте DECLARE_ABSTRACT_CLASS(class) и IMPLEMENT_ABSTRACT_CLASS(class, baseClass) для описания абстрактных классов.

Используйте DECLARE_CLASS2(class) и IMPLEMENT_CLASS2(class, baseClass1, baseClass2) при наличии двух базовых классов.

Используйте DECLARE_APP(class) и IMPLEMENT_APP(class) чтобы сделать класс приложения известным wxWidgets.

wxConstCast(ptr, class) это макрос разворачивающийся в
const_cast<class *>(ptr) если компилятор поддерживает const_cast или в старое синтаксиси приведения типов в C-стиле, в противном случае.

wxDynamicCastThis(class) – эквивалент для wxDynamicCast(this, class), но последний может служить причиной предупреждений на некоторых компиляторах (так как он тестирует не указывает ли указатель на NULL, что всегда истинно), таким образом этот макрос следует использовать для устранения этих предупреждений.

wxStaticCast(ptr, class) сначала дополнительно проверяет правильность приведения типов в режиме отладки (вы получите assert в случае если wxDynamicCast(ptr, class) == NULL) и затем возвращает результат выполнения
static_cast<class*>(ptr).

wx_const_cast(T, x) тоже самое что и const_cast<T>(x) в случае поддержки этой конструкции компилятором и (T)x для старых компиляторов. В отличии от wxConstCast, этот макрос преобразует к типу T, не к *T, к тому же порядок аргументов в точности соответвует конструкции для стандартного приведения типов.

wx_reinterpret_cast(T, x) тоже самое что и reinterpret_cast<T>(x) для новых компиляторов и (T)x для старых.

wx_static_cast(T, x) тоже самое static_cast<T>(x) или (T)x…. В отличии от wxStaticCast, не делается ни каких дополнительных проверок, и значение аргументов в точности совпадает со стандартным static_cast, T – полное имя типа (* автоматически не добавляется).

Related:

Comments are closed.