如何在C ++中实现元类?

时间:2009-04-13 23:45:14

标签: c++ metaclass

我一直在读一些关于元类的内容,但我想知道它们是否可以用C ++实现。

我知道Qt库正在使用MetaObjects,但它使用C ++的扩展来实现它。我想知道是否可以直接在C ++中使用。

感谢。

6 个答案:

答案 0 :(得分:3)

Gamma等人的“设计模式”一书中的一些模式具有与元类概念类似的特征。例如,“策略”模式允许您在创建时自定义对象行为。信封成语是另一个紧密的匹配。但是,不要让你自定义类的接口。

在COM中,IDispatch接口允许在运行时向对象动态添加方法/属性。但这意味着放弃标准的c ++方法调用。每个调用都通过相同的方法,它将索引或字符串键转换为用户维护的方法/属性表,并且所有参数必须作为对象数组传递。

使用这两种技术可以获得元类的灵活性,但由于没有语法优点或运行时/编译器帮助,这是一个更难的问题。

戴夫

答案 1 :(得分:3)

如果元类的工作定义是“实例化本身就是类的语言实体”,则泛型是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&lt; double&gt;在倒数第二行中强制编译器实例化Meta&lt; double&gt;类; sizeof运算符对Meta进行操作,从而证明这不仅仅是语义糖,而且已经实例化了类。即使没有实例化Meta类型的对象,该程序也已完成。

答案 2 :(得分:3)

C ++没有对元类的内置支持(不是以Python / Objective-C方式),但是您可以手动模仿元类的行为。基础非常简单,您可以创建一个具有更长寿命的额外类(Singleton,静态对象或Construct On First Use Idiom),它可以创建和操作它的相应类。 (在Objective-C中,元类通常包含'静态'成员变量,内存分配/释放例程等等。)

Qt所做的是,他们采用了元类的概念并对其进行了修改,以便它们可以支持某种形式的反射(以及不支持它的系统上的RTTI)。实现这一点需要大量的宏魔法或自定义编译器(例如他们选择使用)。

一般来说,常规元类提供的大多数功能都是由C ++语言提供的;只是以不同的形式。实际上,你想要元对象的唯一原因是出于反射的目的,在this document中概述了在C ++中实现反射的不同方法。

除此之外,如果你真的设置在Objective-C风格的元类系统上,我不知道有任何库可以做到这一点,但可能很好。另一方面,滚动你自己也不应该那么困难。

答案 3 :(得分:1)

害怕不...至少不是本地人。

拥有元类通常需要有一个表示类的运行时对象,如Java中的情况。

在C ++中,类没有运行时表示。它们的表现形式出现在虚拟表中。但在许多方面,它们像C函数一样运行,所有OOP几乎都作为粘合代码运行。

话虽这么说,你可能希望用其他语言的元类实现很多东西的OOP模式。您还可以“模拟”自己的对象系统。

答案 4 :(得分:1)

可以创建元类,但是C ++与此不同,它是基于静态编译时的实现,而不是运行时灵活性。

无论如何,这取决于你是想要带有方法的元类还是带有数据的元类,可以使用像boost :: any这样的Boost构造来实现Data类,如果你想要带有方法的Classes,你可以使用boost: :绑定到对象的绑定方法,或者您可以使用单入口点接口(如COM对象)自己实现它们。

然而,“真正的”C ++方式是使用泛型,所以它可以在编译时确定,以获得最佳性能。

说实话,我见过很少的系统,虽然我已经看到了一些,确实需要运行时灵活性,但在大多数情况下,对象出生并死于同一类,或者至少足以花费95%的生命周期一旦他们走出工厂就成为一个单一的班级。

因此,在许多情况下,人们发现自己为运行时元类付出的代价太高了。当然,有一种观点认为这可以提供更好的开发人员性能,但在许多情况下,每行代码将在硬件上运行比写入代码所花费的时间多几亿倍。因此,您可以将编译时和运行时类视为前期支付或租赁。就个人而言,我喜欢预付款。

答案 5 :(得分:1)

您可能需要查看此博文。

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

Meta类可能会进入C ++,但还需要一段时间。