2012-02-28 2 views
3

У меня здесь есть проблема. Я работаю над библиотекой отражений, как с упражнениями, так и с утилитами для будущих проектов. Чтобы заставить его работать, я уже согласился с тем, что неизбежно быть навязчивым, и мне нужно будет добавить, по крайней мере, немного кода для тела класса, чтобы получить ценные данные отражения.Реализация рефлексии: как найти родителя класса

Однако я хотел бы быть как можно более минималистичным. Итак, изучив некоторые существующие реализации, я нашел концепцию, которая мне подходит. Для упрощения, картина выглядит следующим образом:

class Base 
{ 
    int baseFoo; 
    double baseBar[5]; 
    RTTINFO(baseFoo, baseBar); 
}; 

(...) 

Base sth; 
std::cout << TypeInfo(sth).variables[0].name; << std::endl; 
// I don't mind if the way of accessing the type info changes totally 

Используя некоторые общие программирования, я могу достичь в значительной степени скрывается что-то мне нравится за этим RTTINFO макро и построения информационного типа структур. Я могу получить типы, имена, размер массива и т.д. Но когда я хочу пойти на один шаг дальше и ввести наследование, например:

class Derived : public Base 
{ 
    std::string foo; 
    char* bar; 
    /* RTTIPARENT(Base); <-- I want to avoid this */ 
    RTTINFO(foo, bar); 
}; 

, то я бы хотел, чтобы избежать базы и задав все еще быть в состоянии получить в его RTTI членов. Я надеялся, что есть некоторая дорога для Base, чтобы пронести какие-то намеки в ее RTTINFO(...) за Derived, чтобы сделать это возможным. Так .. есть?

Основные требования:

  1. Я не хочу, чтобы указать базовый класс в любом месте, но язык определенные места. И я не хочу обертывать class Derived : public Base в любом макросе.
  2. RTTIINFO может добавить к затронутому классу любые смещения языка и памяти.
  3. Я могу положить все, что захочу, в RTTINFO макрос, даже тонны кода при необходимости.
  4. И базовый, и производный используют тот же самый RTTINFO макрос, который может быть использован повторно в дальнейшем, конечно. Оставим проблему множественного наследования, одно наследование кажется достаточно сложным.
  5. Для доступа к RTTI BaseDerived, это может быть любой другой внешний вспомогательный класс/функция, которая будет обрабатывать данные RTTI. Однако необходимо поддерживать частные переменные-члены.
  6. Я не возражаю против затрат на компиляцию и время исполнения - если какие-либо вычисления, такие как построение дерева наследования, опрос всех существующих классов, что бы то ни было, должны выполняться во время выполнения, всегда можно переместить его на этап инициализации программы, так что для меня это не очень важно.
  7. Если возможно, избегайте RTTI с поддержкой языков, поскольку я должен быть отключен в некоторых проектах. Во всяком случае, я не нашел решения даже с ним.
  8. Дополнительный этап компиляции не может быть добавлен.

Одно примечание: Может быть, я мог бы использовать type_info::before(), но даже если она будет работать для обычных компиляторов, стандарт C++ говорит, что я не могу полагаться на наследование отношений здесь.

Спасибо за любые предложения!

Andrew

+1

Как получить текущее имя класса в макросе? –

+5

Reflection принадлежит к вашему C + + «Утилите для будущего», так как бензопила принадлежит к практике дантиста. –

+0

Точно, если вы хотите получить какую-либо информацию о отражении/типе, у вас будет столько макросов, что это будет бесполезно. Просто посмотрите на GObject – farnoy

ответ

3

Вы не будете иметь полное отражение с текущей C++ 03 или C++ 11 компиляторов (потому что даже C++ 11 не имеют реального отражения).

Вы можете сгенерировать мета-класс код (смотреть на Qt MOC как хороший пример)

Вы можете расширить свой C++ компилятор. Если это GCC, подумайте о создании плагина или расширения MELT.

+0

Вот почему я добавил 8). Для меня добавление нового этапа компиляции имеет так много недостатков, что я бы лучше отказался от любых попыток заставить отражения работать. – Andrew

+0

Затем вам нужно сгенерировать код метакласса C++, например Qt. Возможно, вы считали, что используете 'QObject' (то есть QCore, без какого-либо графического интерфейса)? –

+0

Спасибо за предложения, действительно, QObject будет делать, но для этого все еще нужен 'moc'. Я не был достаточно ясен - «дополнительным шагом компиляции» я имею в виду также генерацию кода и предварительную обработку. Однако, как вы думаете, возможно ли использовать расширения Qt только в конфигурации отладки и поддерживать совместимость проекта (включая SCM) в одно и то же время? Или это не стоит? – Andrew

2

Вы можете использовать генерацию кода, создав своего рода DSL (Domain Specific Language) и небольшую структуру генерации кода, которая будет отражать материал для вас на основе описаний классов в этой DSL. Вероятно, это работает только для части данных и наследования, а не для поведенческой части (т. Е. Методов), но поскольку большинство сторонников Java в любом случае предпочитают модель анемичного объекта, это идеально вписывается в эту тенденцию.

И поскольку C++ имеет истинное множественное наследование, вы можете преодолеть этот недостаток и вывести свои классы поведения из сгенерированных.

Stefan

Смежные вопросы