Как я могу реализовать метаклассы в C ++? - PullRequest
2 голосов
/ 14 апреля 2009

Я немного читал о том, что такое метаклассы, но я хотел бы знать, можно ли их достичь в C ++.

Я знаю, что библиотека Qt использует MetaObjects, но для этого она использует расширение C ++. Я хочу знать, возможно ли это прямо в C ++.

Спасибо.

Ответы [ 6 ]

3 голосов
/ 14 апреля 2009

C ++ Не имеет встроенной поддержки мета-классов (не в стиле Python / Objective-C), однако вы можете вручную имитировать поведение мета-классов. Основы довольно просты: вы создаете дополнительный класс с более длительным сроком службы (Singleton, статический объект или Construct On First Use Idiom ), который может создавать и управлять соответствующим классом. (В Objective-C мета-класс обычно содержит «статические» переменные-члены, процедуры выделения / освобождения памяти и так далее).

Что Qt сделал, так это то, что они взяли концепцию мета-классов и изменили ее так, чтобы они могли поддерживать некоторую форму Reflection (и RTTI в системах, которые не поддерживают ее). Для реализации этого потребуется либо много магии макросов, либо собственный компилятор (такой, какой они решили использовать).

Как правило, большинство функций, предоставляемых обычным метаклассом, уже обеспечивается языком C ++; просто в другой форме. И действительно, единственная причина, по которой вы хотели бы, чтобы мета-объекты были для целей отражения, есть различные способы реализовать отражение в C ++, как описано в этом документе .

Кроме того, если вы действительно настроены на систему мета-классов в стиле Objective-C, я не знаю ни о каких библиотеках, которые бы это делали, но они вполне могли бы быть. С другой стороны, кататься самостоятельно тоже не составит труда.

3 голосов
/ 14 апреля 2009

Если рабочим определением метакласса является «языковая сущность, экземплярами которой являются сами классы», то generics являются метаклассами в C ++:

#include <iostream>
using namespace std;

template <typename T>
class Meta {
public:
    Meta(const T&init) : mData(init) {}
// ...
private:
    T mData;

};

int main(int, char **) {
  cout << "The size of Meta<double> is " << sizeof(Meta<double>) << endl ;
  return 0;
}

Использование Meta в предпоследней строке вынуждает компилятор создавать экземпляр класса Meta ; Оператор sizeof работает с Meta, демонстрируя тем самым, что это не просто семантический сахар и что экземпляр класса создан. Программа завершена, даже если не созданы объекты типа Meta.

3 голосов
/ 14 апреля 2009

Некоторые из паттернов в книге «Шаблоны проектирования» Гаммы и др. Имеют сходные черты с концепцией метакласса. Например, шаблон «Стратегия» позволяет настроить поведение объекта во время создания. Письмо-конверт идиома является еще одним близким совпадением. Однако не позволяйте настраивать интерфейс для класса.

В COM интерфейс IDispatch позволяет динамически добавлять методы / атрибуты к объекту во время выполнения. Это означает отказ от стандартных вызовов метода c ++. Каждый вызов проходит через один и тот же метод, который переносит индексный или строковый ключ в таблицу методов / свойств, поддерживаемую пользователем, и все параметры должны передаваться как массив объектов.

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

Dave

1 голос
/ 14 августа 2017

Возможно, вы захотите взглянуть на этот пост в блоге.

https://herbsutter.com/2017/07/26/metaclasses-thoughts-on-generative-c/

Возможно, что мета-классы попадут в C ++, но это еще не скоро.

1 голос
/ 14 апреля 2009

Можно создавать мета-классы, однако C ++ не об этом, а о статически реализованных реализациях во время компиляции, а не о гибкости во время выполнения.

В любом случае, если вам нужны метаклассы с методами или просто метаклассы с данными, классы данных могут быть реализованы с помощью конструкций Boost, таких как boost :: any, а если вам нужны классы с методами, вы можете использовать boost: : bind для привязки методов к объекту, или вы можете реализовать их самостоятельно с помощью интерфейса с одной точкой входа, такого как COM-объекты.

Однако «настоящий» способ C ++ - это использование обобщений, чтобы все они могли быть определены во время компиляции для лучшей производительности.

Если честно, я видел очень мало систем, хотя я видел некоторые, которые действительно нуждаются в гибкости во время выполнения, в большинстве случаев объекты рождаются и умирают в одном классе, или, по крайней мере, достаточно, чтобы тратить 95% своей жизни. как один класс, когда они выходят из своей фабрики.

Так что во многих ситуациях приходится платить слишком много за мета-классы времени выполнения. Конечно, существует мнение, что это обеспечивает лучшую производительность для разработчиков, но во многих ситуациях каждая строка кода будет выполняться на оборудовании в несколько сотен миллионов раз больше, чем время, затрачиваемое на ее написание. Таким образом, вы можете думать о классах времени компиляции и времени исполнения как о предоплате или лизинге навсегда. Лично мне нравится платить авансом.

1 голос
/ 14 апреля 2009

Бояться нет ... По крайней мере, не изначально.

Наличие метакласса обычно требует наличия объекта времени выполнения, представляющего класс, как в случае с Java.

В C ++ классы не имеют представления времени выполнения. Их проявления происходят в таких вещах, как виртуальный стол. Но во многих отношениях они работают как функции C, а ООП функционирует почти как связующий код.

При этом существуют шаблоны ООП для многих вещей, которые вы, возможно, захотите реализовать с помощью метакласса на других языках. Вы также можете «смоделировать» свою собственную объектную систему.

...